http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zkperl/t/10_invalid.t ---------------------------------------------------------------------- diff --git a/zookeeper-contrib/zookeeper-contrib-zkperl/t/10_invalid.t b/zookeeper-contrib/zookeeper-contrib-zkperl/t/10_invalid.t new file mode 100644 index 0000000..5e080b6 --- /dev/null +++ b/zookeeper-contrib/zookeeper-contrib-zkperl/t/10_invalid.t @@ -0,0 +1,773 @@ +# 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 => 107; + +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(1); + + +## new() + +eval { + Net::ZooKeeper->new(); +}; +like($@, qr/Usage: Net::ZooKeeper::new\(package, hosts, \.\.\.\)/, + 'new(): no hostname specified'); + +eval { + Net::ZooKeeper->new($hosts, 'bar'); +}; +like($@, qr/invalid number of arguments/, + 'new(): invalid number of arguments'); + +eval { + Net::ZooKeeper->new($hosts, 'session_timeout' => -3); +}; +like($@, qr/invalid session timeout/, + 'new(): invalid session timeout'); + +eval { + Net::ZooKeeper->new($hosts, 'session_timeout' => 0x4000_0000); +}; +like($@, qr/invalid session timeout/, + 'new(): invalid session timeout'); + +eval { + Net::ZooKeeper->new($hosts, 'session_id' => 'abcdef'); +}; +like($@, qr/invalid session ID/, + 'new(): invalid session ID'); + +my $zkh = Net::ZooKeeper->new($hosts); +isa_ok($zkh, 'Net::ZooKeeper', + 'new(): created handle'); + + +## DESTROY() + +eval { + $zkh->DESTROY('foo'); +}; +like($@, qr/Usage: Net::ZooKeeper::DESTROY\(zkh\)/, + 'DESTROY(): too many arguments'); + +my $bad_zkh = {}; +$bad_zkh = bless($bad_zkh, 'Net::ZooKeeper'); + +my $ret = $bad_zkh->DESTROY(); +ok(!$ret, + 'DESTROY(): no action on invalid handle'); + + +## add_auth() + +eval { + $zkh->add_auth(); +}; +like($@, qr/Usage: Net::ZooKeeper::add_auth\(zkh, scheme, cert\)/, + 'add_auth(): no scheme specified'); + +eval { + $zkh->add_auth('foo'); +}; +like($@, qr/Usage: Net::ZooKeeper::add_auth\(zkh, scheme, cert\)/, + 'add_auth(): no certificate specified'); + +eval { + $zkh->add_auth('foo', 'foo', 'bar'); +}; +like($@, qr/Usage: Net::ZooKeeper::add_auth\(zkh, scheme, cert\)/, + 'add_auth(): too many arguments'); + +eval { + $bad_zkh->add_auth('foo', 'foo'); +}; +like($@, qr/invalid handle/, + 'add_auth(): invalid handle'); + +eval { + Net::ZooKeeper::add_auth(1, 'foo', 'foo'); +}; +like($@, qr/zkh is not a hash reference of type Net::ZooKeeper/, + 'add_auth(): invalid hash reference'); + + +## create() + +eval { + $zkh->create(); +}; +like($@, qr/Usage: Net::ZooKeeper::create\(zkh, path, buf, \.\.\.\)/, + 'create(): no path specified'); + +eval { + $zkh->create($node_path); +}; +like($@, qr/Usage: Net::ZooKeeper::create\(zkh, path, buf, \.\.\.\)/, + 'create(): no data buffer specified'); + +eval { + $zkh->create($node_path, 'foo', 'bar'); +}; +like($@, qr/invalid number of arguments/, + 'create(): invalid number of arguments'); + +eval { + $zkh->create($node_path, 'foo', 'path_read_len' => -3); +}; +like($@, qr/invalid path read length/, + 'create(): invalid path read length'); + +eval { + $zkh->create($node_path, 'foo', 'path_read_len' => 1); +}; +like($@, qr/invalid path read length/, + 'create(): invalid path read length'); + +eval { + $zkh->create($node_path, 'foo', 'flags' => 15); +}; +like($@, qr/invalid create flags/, + 'create(): invalid create flags'); + +eval { + $zkh->create($node_path, 'foo', 'flags' => ZOO_EPHEMERAL, 'acl', 'foo'); +}; +like($@, qr/invalid ACL array reference/, + 'create(): invalid ACL array reference'); + +eval { + $zkh->create($node_path, 'foo', 'acl', {}); +}; +like($@, qr/invalid ACL array reference/, + 'create(): invalid ACL array reference to hash'); + +eval { + my @acl = ('foo', 'bar'); + $zkh->create($node_path, 'foo', 'acl', \@acl); +}; +like($@, qr/invalid ACL entry hash reference/, + 'create(): invalid ACL entry hash reference'); + +eval { + my @acl = ({ 'foo' => 'bar' }); + $zkh->create($node_path, 'foo', 'acl', \@acl); +}; +like($@, qr/no ACL entry perms element/, + 'create(): no ACL entry perms element'); + +eval { + my @acl = ( + { + 'perms' => -1 + } + ); + $zkh->create($node_path, 'foo', 'acl', \@acl); +}; +like($@, qr/invalid ACL entry perms/, + 'create(): invalid ACL entry perms'); + +eval { + my @acl = ( + { + 'perms' => ZOO_PERM_ALL + } + ); + $zkh->create($node_path, 'foo', 'acl', \@acl); +}; +like($@, qr/no ACL entry scheme element/, + 'create(): no ACL entry scheme element'); + +eval { + my @acl = ( + { + 'perms' => ZOO_PERM_ALL, + 'scheme' => 'foo' + } + ); + $zkh->create($node_path, 'foo', 'acl', \@acl); +}; +like($@, qr/no ACL entry id element/, + 'create(): no ACL entry id element'); + +eval { + my @acl = ( + { + 'perms' => ZOO_PERM_ALL, + 'scheme' => 'foo', + 'id' => 'bar' + }, + 'bar' + ); + $zkh->create($node_path, 'foo', 'acl', \@acl); +}; +like($@, qr/invalid ACL entry hash reference/, + 'create(): invalid second ACL entry hash reference'); + +eval { + $bad_zkh->create($node_path, 'foo'); +}; +like($@, qr/invalid handle/, + 'create(): invalid handle'); + +eval { + Net::ZooKeeper::create(1, $node_path, 'foo'); +}; +like($@, qr/zkh is not a hash reference of type Net::ZooKeeper/, + 'create(): invalid hash reference'); + + +## delete() + +eval { + $zkh->delete(); +}; +like($@, qr/Usage: Net::ZooKeeper::delete\(zkh, path, \.\.\.\)/, + 'delete(): no path specified'); + +eval { + $zkh->delete($node_path, 'bar'); +}; +like($@, qr/invalid number of arguments/, + 'delete(): invalid number of arguments'); + +eval { + $zkh->delete($node_path, 'version' => -3); +}; +like($@, qr/invalid version requirement/, + 'delete(): invalid version requirement'); + +eval { + $bad_zkh->delete($node_path); +}; +like($@, qr/invalid handle/, + 'delete(): invalid handle'); + +eval { + Net::ZooKeeper::delete(1, $node_path); +}; +like($@, qr/zkh is not a hash reference of type Net::ZooKeeper/, + 'delete(): invalid hash reference'); + + +## exists() + +eval { + $zkh->exists(); +}; +like($@, qr/Usage: Net::ZooKeeper::exists\(zkh, path, \.\.\.\)/, + 'exists(): no path specified'); + +eval { + $zkh->exists($node_path, 'bar'); +}; +like($@, qr/invalid number of arguments/, + 'exists(): invalid number of arguments'); + +eval { + $zkh->exists($node_path, 'watch', 'bar'); +}; +like($@, qr/watch is not a hash reference of type Net::ZooKeeper::Watch/, + 'exists(): invalid watch hash reference'); + +eval { + $zkh->exists($node_path, 'watch', []); +}; +like($@, qr/watch is not a hash reference of type Net::ZooKeeper::Watch/, + 'exists(): invalid watch hash reference to array'); + +eval { + $zkh->exists($node_path, 'stat', 'bar'); +}; +like($@, qr/stat is not a hash reference of type Net::ZooKeeper::Stat/, + 'exists(): invalid stat hash reference'); + +eval { + $zkh->exists($node_path, 'stat', []); +}; +like($@, qr/stat is not a hash reference of type Net::ZooKeeper::Stat/, + 'exists(): invalid stat hash reference'); + +eval { + $bad_zkh->exists($node_path); +}; +like($@, qr/invalid handle/, + 'exists(): invalid handle'); + +eval { + Net::ZooKeeper::exists(1, $node_path); +}; +like($@, qr/zkh is not a hash reference of type Net::ZooKeeper/, + 'exists(): invalid hash reference'); + + +## get_children() + +eval { + $zkh->get_children(); +}; +like($@, qr/Usage: Net::ZooKeeper::get_children\(zkh, path, \.\.\.\)/, + 'get_children(): no path specified'); + +eval { + $zkh->get_children($node_path, 'bar'); +}; +like($@, qr/invalid number of arguments/, + 'get_children(): invalid number of arguments'); + +eval { + $zkh->get_children($node_path, 'watch', 'bar'); +}; +like($@, qr/watch is not a hash reference of type Net::ZooKeeper::Watch/, + 'get_children(): invalid watch hash reference'); + +eval { + $zkh->get_children($node_path, 'watch', []); +}; +like($@, qr/watch is not a hash reference of type Net::ZooKeeper::Watch/, + 'get_children(): invalid watch ash reference to array'); + +eval { + $bad_zkh->get_children($node_path); +}; +like($@, qr/invalid handle/, + 'get_children(): invalid handle'); + +eval { + Net::ZooKeeper::get_children(1, $node_path); +}; +like($@, qr/zkh is not a hash reference of type Net::ZooKeeper/, + 'get_children(): invalid hash reference'); + + +## get() + +eval { + $zkh->get(); +}; +like($@, qr/Usage: Net::ZooKeeper::get\(zkh, path, \.\.\.\)/, + 'get(): no path specified'); + +eval { + $zkh->get($node_path, 'bar'); +}; +like($@, qr/invalid number of arguments/, + 'get(): invalid number of arguments'); + +eval { + $zkh->get($node_path, 'data_read_len' => -3); +}; +like($@, qr/invalid data read length/, + 'get(): invalid data read length'); + +eval { + $zkh->get($node_path, 'data_read_len' => 10, 'watch', 'bar'); +}; +like($@, qr/watch is not a hash reference of type Net::ZooKeeper::Watch/, + 'get(): invalid watch hash reference'); + +eval { + $zkh->get($node_path, 'watch', []); +}; +like($@, qr/watch is not a hash reference of type Net::ZooKeeper::Watch/, + 'get(): invalid watch hash reference to array'); + +eval { + $zkh->get($node_path, 'stat', 'bar'); +}; +like($@, qr/stat is not a hash reference of type Net::ZooKeeper::Stat/, + 'get(): invalid stat hash reference'); + +eval { + $zkh->get($node_path, 'stat', []); +}; +like($@, qr/stat is not a hash reference of type Net::ZooKeeper::Stat/, + 'get(): invalid stat hash reference'); + +eval { + $bad_zkh->get($node_path); +}; +like($@, qr/invalid handle/, + 'get(): invalid handle'); + +eval { + Net::ZooKeeper::get(1, $node_path); +}; +like($@, qr/zkh is not a hash reference of type Net::ZooKeeper/, + 'get(): invalid hash reference'); + + +## set() + +eval { + $zkh->set(); +}; +like($@, qr/Usage: Net::ZooKeeper::set\(zkh, path, buf, \.\.\.\)/, + 'set(): no path specified'); + +eval { + $zkh->set($node_path); +}; +like($@, qr/Usage: Net::ZooKeeper::set\(zkh, path, buf, \.\.\.\)/, + 'set(): no data buffer specified'); + +eval { + $zkh->set($node_path, 'foo', 'bar'); +}; +like($@, qr/invalid number of arguments/, + 'set(): invalid number of arguments'); + +eval { + $zkh->set($node_path, 'foo', 'version' => -3); +}; +like($@, qr/invalid version requirement/, + 'set(): invalid version requirement'); + +eval { + $zkh->set($node_path, 'foo', 'version', 0, 'stat', 'bar'); +}; +like($@, qr/stat is not a hash reference of type Net::ZooKeeper::Stat/, + 'set(): invalid stat hash reference'); + +eval { + $zkh->set($node_path, 'foo', 'stat', []); +}; +like($@, qr/stat is not a hash reference of type Net::ZooKeeper::Stat/, + 'set(): invalid stat hash reference'); + +eval { + $bad_zkh->set($node_path, 'foo'); +}; +like($@, qr/invalid handle/, + 'set(): invalid handle'); + +eval { + Net::ZooKeeper::set(1, $node_path, 'foo'); +}; +like($@, qr/zkh is not a hash reference of type Net::ZooKeeper/, + 'set(): invalid hash reference'); + + +## get_acl() + +eval { + $zkh->get_acl(); +}; +like($@, qr/Usage: Net::ZooKeeper::get_acl\(zkh, path, \.\.\.\)/, + 'get_acl(): no path specified'); + +eval { + $zkh->get_acl($node_path, 'bar'); +}; +like($@, qr/invalid number of arguments/, + 'get_acl(): invalid number of arguments'); + +eval { + $zkh->get_acl($node_path, 'stat', 'bar'); +}; +like($@, qr/stat is not a hash reference of type Net::ZooKeeper::Stat/, + 'get_acl(): invalid stat hash reference'); + +eval { + $zkh->get_acl($node_path, 'stat', []); +}; +like($@, qr/stat is not a hash reference of type Net::ZooKeeper::Stat/, + 'get_acl(): invalid stat hash reference'); + +eval { + $bad_zkh->get_acl($node_path); +}; +like($@, qr/invalid handle/, + 'get_acl(): invalid handle'); + +eval { + Net::ZooKeeper::get_acl(1, $node_path); +}; +like($@, qr/zkh is not a hash reference of type Net::ZooKeeper/, + 'get_acl(): invalid hash reference'); + + +## set_acl() + +eval { + $zkh->set_acl(); +}; +like($@, qr/Usage: Net::ZooKeeper::set_acl\(zkh, path, acl_arr, \.\.\.\)/, + 'set_acl(): no path specified'); + +eval { + $zkh->set_acl($node_path); +}; +like($@, qr/Usage: Net::ZooKeeper::set_acl\(zkh, path, acl_arr, \.\.\.\)/, + 'set_acl(): no data buffer specified'); + +eval { + $zkh->set_acl($node_path, 'foo'); +}; +like($@, qr/acl_arr is not an array reference/, + 'set_acl(): invalid ACL array reference'); + +eval { + $zkh->set_acl($node_path, {}); +}; +like($@, qr/acl_arr is not an array reference/, + 'set_acl(): invalid ACL array reference to hash'); + +eval { + my @acl = ('foo', 'bar'); + $zkh->set_acl($node_path, \@acl); +}; +like($@, qr/invalid ACL entry hash reference/, + 'set_acl(): invalid ACL entry hash reference'); + +eval { + my @acl = ({ 'foo' => 'bar' }); + $zkh->set_acl($node_path, \@acl); +}; +like($@, qr/no ACL entry perms element/, + 'set_acl(): no ACL entry perms element'); + +eval { + my @acl = ( + { + 'perms' => -1 + } + ); + $zkh->set_acl($node_path, \@acl); +}; +like($@, qr/invalid ACL entry perms/, + 'set_acl(): invalid ACL entry perms'); + +eval { + my @acl = ( + { + 'perms' => ZOO_PERM_ALL + } + ); + $zkh->set_acl($node_path, \@acl); +}; +like($@, qr/no ACL entry scheme element/, + 'set_acl(): no ACL entry scheme element'); + +eval { + my @acl = ( + { + 'perms' => ZOO_PERM_ALL, + 'scheme' => 'foo' + } + ); + $zkh->set_acl($node_path, \@acl); +}; +like($@, qr/no ACL entry id element/, + 'set_acl(): no ACL entry id element'); + +eval { + my @acl = ( + { + 'perms' => ZOO_PERM_ALL, + 'scheme' => 'foo', + 'id' => 'bar' + }, + 'bar' + ); + $zkh->set_acl($node_path, \@acl); +}; +like($@, qr/invalid ACL entry hash reference/, + 'set_acl(): invalid second ACL entry hash reference'); + +eval { + $zkh->set_acl($node_path, [], 'bar'); +}; +like($@, qr/invalid number of arguments/, + 'set_acl(): invalid number of arguments'); + +eval { + $zkh->set_acl($node_path, [], 'version' => -3); +}; +like($@, qr/invalid version requirement/, + 'set_acl(): invalid version requirement'); + +eval { + $bad_zkh->set_acl($node_path, []); +}; +like($@, qr/invalid handle/, + 'set_acl(): invalid handle'); + +eval { + Net::ZooKeeper::set_acl(1, $node_path, []); +}; +like($@, qr/zkh is not a hash reference of type Net::ZooKeeper/, + 'set_acl(): invalid hash reference'); + + +## stat() + +eval { + $zkh->stat('bar'); +}; +like($@, qr/Usage: Net::ZooKeeper::stat\(zkh\)/, + 'stat(): too many arguments'); + +eval { + $bad_zkh->stat(); +}; +like($@, qr/invalid handle/, + 'stat(): invalid handle'); + +eval { + Net::ZooKeeper::stat(1); +}; +like($@, qr/zkh is not a hash reference of type Net::ZooKeeper/, + 'stat(): invalid hash reference'); + +my $stat = $zkh->stat(); +isa_ok($stat, 'Net::ZooKeeper::Stat', + 'stat(): created stat handle'); + + +## stat DESTROY() + +eval { + $stat->DESTROY('foo'); +}; +like($@, qr/Usage: Net::ZooKeeper::Stat::DESTROY\(zksh\)/, + 'stat DESTROY(): too many arguments'); + +my $bad_stat = {}; +$bad_stat = bless($bad_stat, 'Net::ZooKeeper::Stat'); + +$ret = $bad_stat->DESTROY(); +ok(!$ret, + 'stat DESTROY(): no action on invalid handle'); + + +## watch() + +eval { + $zkh->watch('bar'); +}; +like($@, qr/invalid number of arguments/, + 'watch(): invalid number of arguments'); + +eval { + $bad_zkh->watch(); +}; +like($@, qr/invalid handle/, + 'watch(): invalid handle'); + +eval { + Net::ZooKeeper::watch(1); +}; +like($@, qr/zkh is not a hash reference of type Net::ZooKeeper/, + 'watch(): invalid hash reference'); + +my $watch = $zkh->watch(); +isa_ok($watch, 'Net::ZooKeeper::Watch', + 'watch(): created watch handle'); + + +## watch DESTROY() + +eval { + $watch->DESTROY('foo'); +}; +like($@, qr/Usage: Net::ZooKeeper::Watch::DESTROY\(zkwh\)/, + 'watch DESTROY(): too many arguments'); + +my $bad_watch = {}; +$bad_watch = bless($bad_watch, 'Net::ZooKeeper::Watch'); + +$ret = $bad_watch->DESTROY(); +ok(!$ret, + 'watch DESTROY(): no action on invalid handle'); + + +## wait() + +eval { + $watch->wait('bar'); +}; +like($@, qr/invalid number of arguments/, + 'wait(): invalid number of arguments'); + +eval { + $bad_watch->wait(); +}; +like($@, qr/invalid handle/, + 'wait(): invalid watch handle'); + +eval { + Net::ZooKeeper::Watch::wait(1); +}; +like($@, qr/zkwh is not a hash reference of type Net::ZooKeeper::Watch/, + 'wait(): invalid watch hash reference'); + + +## set_log_level() + +eval { + my $f = \&Net::ZooKeeper::set_log_level; + &$f(); +}; +like($@, qr/Usage: Net::ZooKeeper::set_log_level\(level\)/, + 'set_log_level(): no level specified'); + +eval { + my $f = \&Net::ZooKeeper::set_log_level; + &$f(ZOO_LOG_LEVEL_OFF, 'foo'); +}; +like($@, qr/Usage: Net::ZooKeeper::set_log_level\(level\)/, + 'set_log_level(): too many arguments'); + +eval { + Net::ZooKeeper::set_log_level((ZOO_LOG_LEVEL_OFF) - 1); +}; +like($@, qr/invalid log level/, + 'set_log_level(): invalid low log level'); + +eval { + Net::ZooKeeper::set_log_level((ZOO_LOG_LEVEL_DEBUG) + 1); +}; +like($@, qr/invalid log level/, + 'set_log_level(): invalid high log level'); + + +## set_deterministic_conn_order() + +eval { + my $f = \&Net::ZooKeeper::set_deterministic_conn_order; + &$f(); +}; +like($@, qr/Usage: Net::ZooKeeper::set_deterministic_conn_order\(flag\)/, + 'set_deterministic_conn_order(): no flag specified'); + +eval { + my $f = \&Net::ZooKeeper::set_deterministic_conn_order; + &$f(1, 'foo'); +}; +like($@, qr/Usage: Net::ZooKeeper::set_deterministic_conn_order\(flag\)/, + 'set_deterministic_conn_order(): too many arguments'); +
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zkperl/t/15_thread.t ---------------------------------------------------------------------- diff --git a/zookeeper-contrib/zookeeper-contrib-zkperl/t/15_thread.t b/zookeeper-contrib/zookeeper-contrib-zkperl/t/15_thread.t new file mode 100644 index 0000000..1ef56d0 --- /dev/null +++ b/zookeeper-contrib/zookeeper-contrib-zkperl/t/15_thread.t @@ -0,0 +1,121 @@ +# 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 Config; +use File::Spec; +use Test::More; + +BEGIN { + if ($Config{'useithreads'}) { + plan tests => 10; + } + else { + plan skip_all => 'no thread support'; + } +} + +use threads; + +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); + + +my $zkh = Net::ZooKeeper->new($hosts); + +SKIP: { + skip 'no valid handle', 9 unless (defined($zkh)); + + my($thread) = threads->new(\&thread_test, $zkh); + + SKIP: { + skip 'no valid thread', 3 unless (defined($thread)); + + my(@ret) = $thread->join; + + ok((@ret == 3 and $ret[0]), + 'CLONE_SKIP(): handle reference after spawning thread'); + + ok((@ret == 3 and $ret[1]), + 'CLONE_SKIP(): scalar handle reference after spawning thread'); + + ok((@ret == 3 and $ret[2]), + 'CLONE_SKIP(): undef handle reference after spawning thread'); + } + + my $stat = $zkh->stat(); + + ($thread) = threads->new(\&thread_test, $stat); + + SKIP: { + skip 'no valid thread', 3 unless (defined($thread)); + + my(@ret) = $thread->join; + + ok((@ret == 3 and $ret[0]), + 'stat CLONE_SKIP(): stat handle reference after spawning thread'); + + ok((@ret == 3 and $ret[1]), + 'stat CLONE_SKIP(): scalar stat handle reference after ' . + 'spawning thread'); + + ok((@ret == 3 and $ret[2]), + 'stat CLONE_SKIP(): undef stat handle reference after ' . + 'spawning thread'); + } + + my $watch = $zkh->watch(); + + ($thread) = threads->new(\&thread_test, $watch); + + SKIP: { + skip 'no valid thread', 3 unless (defined($thread)); + + my(@ret) = $thread->join; + + ok((@ret == 3 and $ret[0]), + 'watch CLONE_SKIP(): watch handle reference after spawning thread'); + + ok((@ret == 3 and $ret[1]), + 'watch CLONE_SKIP(): scalar watch handle reference after ' . + 'spawning thread'); + + ok((@ret == 3 and $ret[2]), + 'watch CLONE_SKIP(): undef watch handle reference after ' . + 'spawning thread'); + } +} + +sub thread_test +{ + my $zkh = shift; + + my @ret; + + $ret[0] = ref($zkh) ? 1 : 0; + $ret[1] = ($ret[0] and ref($zkh) eq 'SCALAR') ? 1 : 0; + $ret[2] = ($ret[1] and !defined(${$zkh})) ? 1 : 0; + + return @ret; +} + http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zkperl/t/20_tie.t ---------------------------------------------------------------------- diff --git a/zookeeper-contrib/zookeeper-contrib-zkperl/t/20_tie.t b/zookeeper-contrib/zookeeper-contrib-zkperl/t/20_tie.t new file mode 100644 index 0000000..37e9a4f --- /dev/null +++ b/zookeeper-contrib/zookeeper-contrib-zkperl/t/20_tie.t @@ -0,0 +1,353 @@ +# 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 => 54; + +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); + + skip 'no valid handle', 4 unless (defined($zkh)); + + + ## DESTROY() + + my $attr = tied(%{$zkh}); + + my $ret = $attr->DESTROY(); + ok($ret, + 'DESTROY(): destroyed inner hash'); + + $ret = $attr->DESTROY(); + ok(!$ret, + 'DESTROY(): no action on destroyed inner hash'); + + $ret = $zkh->DESTROY(); + ok(!$ret, + 'DESTROY(): no action on handle with destroyed inner hash'); + + undef $zkh; + ok(!defined($zkh), + 'undef: released handle with destroyed inner hash'); +} + +SKIP: { + my $zkh = Net::ZooKeeper->new($hosts); + + skip 'no valid handle', 49 unless (defined($zkh)); + + + ## TIEHASH(), UNTIE() + + eval { + tie(%{$zkh}, 'Net::ZooKeeper'); + }; + like($@, qr/tying hashes of class Net::ZooKeeper not supported/, + 'tie(): tying hashes not supported'); + + eval { + Net::ZooKeeper::TIEHASH('Net::ZooKeeper'); + }; + like($@, qr/tying hashes of class Net::ZooKeeper not supported/, + 'TIEHASH(): tying hashes not supported'); + + eval { + untie(%{$zkh}); + }; + like($@, qr/untying hashes of class Net::ZooKeeper not supported/, + 'untie(): untying hashes not supported'); + + my $attr = tied(%{$zkh}); + + eval { + $attr->UNTIE(0); + }; + like($@, qr/untying hashes of class Net::ZooKeeper not supported/, + 'UNTIE(): untying hashes not supported'); + + + ## FIRSTKEY(), NEXTKEY(), SCALAR() + + my $copy_zkh; + { + my %copy_zkh = %{$zkh}; + $copy_zkh = \%copy_zkh; + } + bless($copy_zkh, 'Net::ZooKeeper'); + is(ref($copy_zkh), 'Net::ZooKeeper', + 'FIRSTKEY(), NEXTKEY(): copied dereferenced handle'); + + eval { + my $val = $copy_zkh->FIRSTKEY(); + }; + like($@, qr/invalid handle/, + 'FETCHKEY(): invalid handle'); + + eval { + my $val = $copy_zkh->NEXTKEY('data_read_len'); + }; + like($@, qr/invalid handle/, + 'NEXTKEY(): invalid handle'); + + my @keys = keys(%{$zkh}); + is(scalar(@keys), 7, + 'keys(): count of keys from handle'); + + @keys = keys(%{$copy_zkh}); + is(scalar(@keys), 7, + 'keys(): count of keys from copied dereferenced handle'); + + is($attr->FIRSTKEY(), 'data_read_len', + 'FIRSTKEY(): retrieved first key using inner hash'); + + is($attr->NEXTKEY('session_id'), 'pending_watches', + 'NEXTKEY(): retrieved last key using inner hash'); + + is($attr->NEXTKEY('pending_watches'), undef, + 'NEXTKEY(): undef returned after last key using inner hash'); + + ok(scalar(%{$zkh}), + 'scalar(): true value returned for dereferenced handle'); + + ok($zkh->SCALAR(), + 'SCALAR(): true value returned'); + + + ## FETCH() + + eval { + my $val = $copy_zkh->FETCH('data_read_len'); + }; + like($@, qr/invalid handle/, + 'FETCH(): invalid handle'); + + { + my $msg; + + $SIG{'__WARN__'} = sub { $msg = $_[0]; }; + + my $val = $zkh->{'foo'}; + ok(!defined($val), + 'FETCH(): undef returned for invalid element'); + + like($msg, qr/invalid element/, + 'FETCH(): invalid element'); + } + + is($zkh->{'data_read_len'}, 1023, + 'FETCH(): default data read length'); + + is($zkh->{'path_read_len'}, 1023, + 'FETCH(): default path read length'); + + is($zkh->{'hosts'}, $hosts, + 'FETCH(): server hosts'); + + is($zkh->{'session_timeout'}, 10000, + 'FETCH(): default session timeout'); + + ok(defined($zkh->{'session_id'}), + 'FETCH(): session ID'); + + SKIP: { + my $zkh = Net::ZooKeeper->new('0.0.0.0:0'); + + skip 'no valid handle with invalid host', 1 unless (defined($zkh)); + + is($zkh->{'session_id'}, '', + 'FETCH(): empty session ID with invalid host'); + } + + is($zkh->{'pending_watches'}, 0, + 'FETCH(): default pending watch list length'); + + is($attr->FETCH('data_read_len'), 1023, + 'FETCH(): default data read length using inner hash'); + + + ## STORE() + + eval { + my $val = $copy_zkh->STORE('data_read_len', 'foo'); + }; + like($@, qr/invalid handle/, + 'STORE(): invalid handle'); + + { + my $msg; + + $SIG{'__WARN__'} = sub { $msg = $_[0]; }; + + $zkh->{'foo'} = 'foo'; + like($msg, qr/invalid element/, + 'STORE(): invalid element'); + } + + eval { + $zkh->{'data_read_len'} = -3; + }; + like($@, qr/invalid data read length/, + 'STORE(): invalid data read length'); + + eval { + $zkh->{'path_read_len'} = -3; + }; + like($@, qr/invalid path read length/, + 'STORE(): invalid path read length'); + + { + my $msg; + + $SIG{'__WARN__'} = sub { $msg = $_[0]; }; + + $zkh->{'hosts'} = 'foo'; + like($msg, qr/read-only element: hosts/, + 'STORE(): read-only server hosts element'); + } + + { + my $msg; + + $SIG{'__WARN__'} = sub { $msg = $_[0]; }; + + $zkh->{'session_timeout'} = 0; + like($msg, qr/read-only element: session_timeout/, + 'STORE(): read-only session timeout element'); + } + + { + my $msg; + + $SIG{'__WARN__'} = sub { $msg = $_[0]; }; + + $zkh->{'session_id'} = 'foo'; + like($msg, qr/read-only element: session_id/, + 'STORE(): read-only session ID element'); + } + + { + my $msg; + + $SIG{'__WARN__'} = sub { $msg = $_[0]; }; + + $zkh->{'pending_watches'} = 0; + like($msg, qr/read-only element: pending_watches/, + 'STORE(): read-only pending watch list length element'); + } + + $zkh->{'data_read_len'} = 200; + is($zkh->{'data_read_len'}, 200, + 'STORE(): updated data read length'); + + $zkh->{'path_read_len'} = 100; + is($zkh->{'path_read_len'}, 100, + 'STORE(): updated path read length'); + + $attr->STORE('data_read_len', 100); + is($zkh->{'data_read_len'}, 100, + 'STORE(): updated data read length using inner hash'); + + + ## EXISTS() + + eval { + my $val = $copy_zkh->EXISTS('data_read_len'); + }; + like($@, qr/invalid handle/, + 'EXISTS(): invalid handle'); + + ok(!exists($zkh->{'foo'}), + 'exists(): invalid element of handle'); + + ok(exists($zkh->{'data_read_len'}), + 'exists(): data read length'); + + ok(exists($zkh->{'path_read_len'}), + 'exists(): path read length'); + + ok(exists($zkh->{'hosts'}), + 'exists(): server hosts'); + + ok(exists($zkh->{'session_timeout'}), + 'exists(): session timeout'); + + ok(exists($zkh->{'session_id'}), + 'exists(): session ID'); + + ok(exists($zkh->{'pending_watches'}), + 'exists(): pending watch list length'); + + ok($attr->EXISTS('data_read_len'), + 'EXISTS(): data read length using inner hash'); + + + ## DELETE(), CLEAR() + + { + my $msg; + + $SIG{'__WARN__'} = sub { $msg = $_[0]; }; + + delete($zkh->{'data_read_len'}); + like($msg, + qr/deleting elements from hashes of class Net::ZooKeeper not supported/, + 'delete(): deleting hash elements not supported'); + } + + { + my $msg; + + $SIG{'__WARN__'} = sub { $msg = $_[0]; }; + + $zkh->DELETE({'data_read_len'}); + like($msg, + qr/deleting elements from hashes of class Net::ZooKeeper not supported/, + 'DELETE(): deleting hash elements not supported'); + } + + { + my $msg; + + $SIG{'__WARN__'} = sub { $msg = $_[0]; }; + + %{$zkh} = (); + like($msg, qr/clearing hashes of class Net::ZooKeeper not supported/, + 'assign: clearing hashes not supported'); + } + + { + my $msg; + + $SIG{'__WARN__'} = sub { $msg = $_[0]; }; + + $zkh->CLEAR(); + like($msg, qr/clearing hashes of class Net::ZooKeeper not supported/, + 'CLEAR(): clearing hashes not supported'); + } +} + http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zkperl/t/22_stat_tie.t ---------------------------------------------------------------------- diff --git a/zookeeper-contrib/zookeeper-contrib-zkperl/t/22_stat_tie.t b/zookeeper-contrib/zookeeper-contrib-zkperl/t/22_stat_tie.t new file mode 100644 index 0000000..02e7913 --- /dev/null +++ b/zookeeper-contrib/zookeeper-contrib-zkperl/t/22_stat_tie.t @@ -0,0 +1,438 @@ +# 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'); + } +} + http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zkperl/t/24_watch_tie.t ---------------------------------------------------------------------- diff --git a/zookeeper-contrib/zookeeper-contrib-zkperl/t/24_watch_tie.t b/zookeeper-contrib/zookeeper-contrib-zkperl/t/24_watch_tie.t new file mode 100644 index 0000000..e77879e --- /dev/null +++ b/zookeeper-contrib/zookeeper-contrib-zkperl/t/24_watch_tie.t @@ -0,0 +1,292 @@ +# 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 => 42; + +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 $watch = $zkh->watch() if (defined($zkh)); + + skip 'no valid watch handle', 4 unless (defined($watch)); + + + ## DESTROY() + + my $attr = tied(%{$watch}); + + my $ret = $attr->DESTROY(); + ok($ret, + 'watch DESTROY(): destroyed inner watch hash'); + + $ret = $attr->DESTROY(); + ok(!$ret, + 'watch DESTROY(): no action on destroyed inner watch hash'); + + $ret = $watch->DESTROY(); + ok(!$ret, + 'watch DESTROY(): no action on watch handle with destroyed inner hash'); + + undef $watch; + ok(!defined($watch), + 'undef: released watch handle with destroyed inner hash'); +} + +SKIP: { + my $zkh = Net::ZooKeeper->new($hosts); + my $watch = $zkh->watch() if (defined($zkh)); + + skip 'no valid watch handle', 37 unless (defined($watch)); + + + ## TIEHASH(), UNTIE() + + eval { + tie(%{$watch}, 'Net::ZooKeeper::Watch'); + }; + like($@, qr/tying hashes of class Net::ZooKeeper::Watch not supported/, + 'tie(): tying watch hashes not supported'); + + eval { + Net::ZooKeeper::Watch::TIEHASH('Net::ZooKeeper::Watch'); + }; + like($@, qr/tying hashes of class Net::ZooKeeper::Watch not supported/, + 'watch TIEHASH(): tying watch hashes not supported'); + + eval { + untie(%{$watch}); + }; + like($@, qr/untying hashes of class Net::ZooKeeper::Watch not supported/, + 'untie(): untying watch hashes not supported'); + + my $attr = tied(%{$watch}); + + eval { + $attr->UNTIE(0); + }; + like($@, qr/untying hashes of class Net::ZooKeeper::Watch not supported/, + 'watch UNTIE(): untying watch hashes not supported'); + + + ## FIRSTKEY(), NEXTKEY(), SCALAR() + + my $copy_watch; + { + my %copy_watch = %{$watch}; + $copy_watch = \%copy_watch; + } + bless($copy_watch, 'Net::ZooKeeper::Watch'); + is(ref($copy_watch), 'Net::ZooKeeper::Watch', + 'watch FIRSTKEY(), NEXTKEY(): copied dereferenced watch handle'); + + eval { + my $val = $copy_watch->FIRSTKEY(); + }; + like($@, qr/invalid handle/, + 'watch FETCHKEY(): invalid watch handle'); + + eval { + my $val = $copy_watch->NEXTKEY('czxid'); + }; + like($@, qr/invalid handle/, + 'watch NEXTKEY(): invalid watch handle'); + + my @keys = keys(%{$watch}); + is(scalar(@keys), 3, + 'keys(): count of keys from watch handle'); + + @keys = keys(%{$copy_watch}); + is(scalar(@keys), 3, + 'keys(): count of keys from copied dereferenced watch handle'); + + is($attr->FIRSTKEY(), 'timeout', + 'watch FIRSTKEY(): retrieved first key using inner watch hash'); + + is($attr->NEXTKEY('event'), 'state', + 'watch NEXTKEY(): retrieved last key using inner watch hash'); + + is($attr->NEXTKEY('state'), undef, + 'NEXTKEY(): undef returned after last key using inner watch hash'); + + ok(scalar(%{$watch}), + 'scalar(): true value returned for dereferenced watch handle'); + + ok($watch->SCALAR(), + 'watch SCALAR(): true value returned'); + + + ## FETCH() + + eval { + my $val = $copy_watch->FETCH('version'); + }; + like($@, qr/invalid handle/, + 'watch FETCH(): invalid watch handle'); + + { + my $msg; + + $SIG{'__WARN__'} = sub { $msg = $_[0]; }; + + my $val = $watch->{'foo'}; + ok(!defined($val), + 'watch FETCH(): undef returned for invalid element'); + + like($msg, qr/invalid element/, + 'watch FETCH(): invalid element'); + } + + is($watch->{'timeout'}, 60000, + 'watch FETCH(): default timeout'); + + is($watch->{'event'}, 0, + 'watch FETCH(): default event'); + + is($watch->{'state'}, 0, + 'watch FETCH(): default state'); + + is($attr->FETCH('timeout'), 60000, + 'watch FETCH(): default timeout using inner watch hash'); + + + ## STORE() + + eval { + my $val = $copy_watch->STORE('version', 'foo'); + }; + like($@, qr/invalid handle/, + 'watch STORE(): invalid watch handle'); + + { + my $msg; + + $SIG{'__WARN__'} = sub { $msg = $_[0]; }; + + $watch->{'foo'} = 'foo'; + like($msg, qr/invalid element/, + 'watch STORE(): invalid element'); + } + + { + my $msg; + + $SIG{'__WARN__'} = sub { $msg = $_[0]; }; + + $watch->{'event'} = 'foo'; + like($msg, qr/read-only element: event/, + 'watch STORE(): read-only event element'); + } + + { + my $msg; + + $SIG{'__WARN__'} = sub { $msg = $_[0]; }; + + $watch->{'state'} = 'foo'; + like($msg, qr/read-only element: state/, + 'watch STORE(): read-only state element'); + } + + $watch->{'timeout'} = 100; + is($watch->{'timeout'}, 100, + 'watch STORE(): updated timeout'); + + $attr->STORE('timeout', 200); + is($watch->{'timeout'}, 200, + 'watch STORE(): updated timeout using inner hash'); + + + ## EXISTS() + + eval { + my $val = $copy_watch->EXISTS('version'); + }; + like($@, qr/invalid handle/, + 'watch EXISTS(): invalid watch handle'); + + ok(!exists($watch->{'foo'}), + 'exists(): invalid element of watch handle'); + + ok(exists($watch->{'timeout'}), + 'exists(): timeout'); + + ok(exists($watch->{'event'}), + 'exists(): event'); + + ok(exists($watch->{'state'}), + 'exists(): state'); + + ok($attr->EXISTS('timeout'), + 'watch EXISTS(): timeout using inner watch hash'); + + + ## DELETE(), CLEAR() + + { + my $msg; + + $SIG{'__WARN__'} = sub { $msg = $_[0]; }; + + delete($watch->{'version'}); + like($msg, + qr/deleting elements from hashes of class Net::ZooKeeper::Watch not supported/, + 'delete(): deleting watch hash elements not supported'); + } + + { + my $msg; + + $SIG{'__WARN__'} = sub { $msg = $_[0]; }; + + $watch->DELETE({'version'}); + like($msg, + qr/deleting elements from hashes of class Net::ZooKeeper::Watch not supported/, + 'watch DELETE(): deleting watch hash elements not supported'); + } + + { + my $msg; + + $SIG{'__WARN__'} = sub { $msg = $_[0]; }; + + %{$watch} = (); + like($msg, qr/clearing hashes of class Net::ZooKeeper::Watch not supported/, + 'assign: clearing watch hashes not supported'); + } + + { + my $msg; + + $SIG{'__WARN__'} = sub { $msg = $_[0]; }; + + $watch->CLEAR(); + like($msg, qr/clearing hashes of class Net::ZooKeeper::Watch not supported/, + 'watch CLEAR(): clearing watch hashes not supported'); + } +} + http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zkperl/t/30_connect.t ---------------------------------------------------------------------- diff --git a/zookeeper-contrib/zookeeper-contrib-zkperl/t/30_connect.t b/zookeeper-contrib/zookeeper-contrib-zkperl/t/30_connect.t new file mode 100644 index 0000000..c2b68bb --- /dev/null +++ b/zookeeper-contrib/zookeeper-contrib-zkperl/t/30_connect.t @@ -0,0 +1,202 @@ +# 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 => 29; + +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); + + +## new(), DESTROY() + +Net::ZooKeeper::set_deterministic_conn_order(1); + +my $zkh = Net::ZooKeeper->new($hosts); +isa_ok($zkh, 'Net::ZooKeeper', + 'new(): created handle'); + +SKIP: { + skip 'no valid handle', 3 unless (defined($zkh)); + + my $ret = $zkh->DESTROY(); + ok($ret, + 'DESTROY(): destroyed handle'); + + $ret = $zkh->DESTROY(); + ok(!$ret, + 'DESTROY(): no action on destroyed handle'); + + undef $zkh; + ok(!defined($zkh), + 'undef: released handle'); +} + +Net::ZooKeeper::set_deterministic_conn_order(0); + +SKIP: { + my $zkh = Net::ZooKeeper->new($hosts); + + skip 'no valid handle', 10 unless (defined($zkh)); + + my $copy_zkh = $zkh; + isa_ok($copy_zkh, 'Net::ZooKeeper', + 'assign: copied handle'); + + my $ret = $zkh->exists($root_path); + ok(defined($ret), + 'exists(): no error from original handle'); + + undef $zkh; + ok(!defined($zkh), + 'undef: released original handle'); + + $ret = $copy_zkh->exists($root_path); + ok(defined($ret), + 'exists(): no error from first copy of handle'); + + $zkh = $copy_zkh; + isa_ok($zkh, 'Net::ZooKeeper', + 'assign: re-copied handle'); + + $ret = $copy_zkh->DESTROY(); + ok($ret, + 'DESTROY(): destroyed first copy of handle'); + + eval { + $zkh->exists($root_path); + }; + like($@, qr/invalid handle/, + 'exists(): invalid second copy of handle'); + + undef $copy_zkh; + ok(!defined($copy_zkh), + 'undef: released first copy of handle'); + + $ret = $zkh->DESTROY(); + ok(!$ret, + 'DESTROY(): no action on second copy of destroyed handle'); + + undef $zkh; + ok(!defined($zkh), + 'undef: released second copy of handle'); +} + +SKIP: { + my $zkh = Net::ZooKeeper->new($hosts); + + skip 'no valid handle', 6 unless (defined($zkh)); + + my $copy_zkh; + { + my %copy_zkh = %{$zkh}; + $copy_zkh = \%copy_zkh; + } + bless($copy_zkh, 'Net::ZooKeeper'); + isa_ok($copy_zkh, 'Net::ZooKeeper', + 'FIRSTKEY(), NEXTKEY(): copied dereferenced handle'); + + eval { + $copy_zkh->exists($root_path); + }; + like($@, qr/invalid handle/, + 'exists(): invalid copy of dereferenced handle'); + + $ret = $copy_zkh->DESTROY(); + ok(!$ret, + 'DESTROY(): no action on copy of dereferenced handle'); + + undef $copy_zkh; + ok(!defined($copy_zkh), + 'undef: released copy of dereferenced handle'); + + my $ret = $zkh->exists($root_path); + ok(defined($ret), + 'exists(): no error from original handle'); + + undef $zkh; + ok(!defined($zkh), + 'undef: released original handle'); +} + +Net::ZooKeeper::set_deterministic_conn_order(1); + +my $zkh1 = Net::ZooKeeper->new($hosts, 'session_timeout' => 0x3FFF_FFFF); +isa_ok($zkh1, 'Net::ZooKeeper', + 'new(): created handle with maximum session timeout'); + +SKIP: { + my $ret = $zkh1->exists($root_path) if (defined($zkh1)); + + skip 'no connection to ZooKeeper', 7 unless + (defined($ret) and $ret); + + + ## FETCH() of read-only attributes + + ok(($zkh1->{'session_timeout'} > 0 and + $zkh1->{'session_timeout'} <= 0x3FFF_FFFF), + 'FETCH(): session timeout reset after connection'); + + my $session_id1 = $zkh1->{'session_id'}; + ok((length($session_id1) > 0), + 'FETCH(): non-empty session ID after connection'); + + SKIP: { + skip 'no session ID after connection', 1 unless + (length($session_id1) > 0); + + my @nonzero_bytes = grep($_ != 0, unpack('c' x length($session_id1), + $session_id1)); + ok((@nonzero_bytes > 0), + 'FETCH(): non-zero session ID after connection'); + } + + ## NOTE: to test re-connections with saved session IDs we create a second + ## connection with the same ID while the first is still active; + ## this is bad practice in normal usage + + my $zkh2 = Net::ZooKeeper->new($hosts, + 'session_id' => $session_id1, + 'session_timeout' => 20000); + isa_ok($zkh2, 'Net::ZooKeeper', + 'new(): created handle with session ID and valid session timeout'); + + $ret = $zkh2->exists($root_path); + ok($ret, + 'new(): reconnection with session ID'); + + SKIP: { + skip 'no connection to ZooKeeper', 2 unless ($ret); + + is($zkh2->{'session_timeout'}, 20000, + 'FETCH(): session timeout unchanged after connection'); + + my $session_id2 = $zkh2->{'session_id'}; + ok((length($session_id2) == length($session_id1) + and $session_id2 eq $session_id1), + 'FETCH(): reconnect with session ID'); + } +} + http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zkperl/t/35_log.t ---------------------------------------------------------------------- diff --git a/zookeeper-contrib/zookeeper-contrib-zkperl/t/35_log.t b/zookeeper-contrib/zookeeper-contrib-zkperl/t/35_log.t new file mode 100644 index 0000000..92821af --- /dev/null +++ b/zookeeper-contrib/zookeeper-contrib-zkperl/t/35_log.t @@ -0,0 +1,88 @@ +# 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 => 3; + +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); + + +my $zkh = Net::ZooKeeper->new($hosts); + +Net::ZooKeeper::set_log_level(ZOO_LOG_LEVEL_INFO); + +SKIP: { + skip 'no valid handle', 2 unless (defined($zkh)); + + SKIP: { + my $dup = 0; + + if (open(OLDERR, '>&', fileno(STDERR))) { + if (close(STDERR) and open(STDERR, '+>', undef)) { + $dup = 1; + + my $old_select = select(STDERR); + $| = 1; + select($old_select); + } + else { + open(STDERR, '>&', fileno(OLDERR)); + close(OLDERR); + } + } + + skip 'no duplicated stderr', 2 unless ($dup); + + SKIP: { + $zkh->exists($root_path); + + sleep(1); + + skip 'no seek on stderr', 1 unless (seek(STDERR, 0, 0)); + + my $log = <STDERR>; + like($log, qr/ZOO_/, + 'exists(): generated log message'); + } + + SKIP: { + $zkh->DESTROY(); + + sleep(1); + + skip 'no seek on stderr', 1 unless (seek(STDERR, 0, 0)); + + my $log = <STDERR>; + like($log, qr/ZOO_/, + 'DESTROY(): generated log message'); + } + + open(STDERR, '>&', fileno(OLDERR)); + close(OLDERR); + } +} + +Net::ZooKeeper::set_log_level(ZOO_LOG_LEVEL_OFF); + http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zkperl/t/40_basic.t ---------------------------------------------------------------------- diff --git a/zookeeper-contrib/zookeeper-contrib-zkperl/t/40_basic.t b/zookeeper-contrib/zookeeper-contrib-zkperl/t/40_basic.t new file mode 100644 index 0000000..38a8a21 --- /dev/null +++ b/zookeeper-contrib/zookeeper-contrib-zkperl/t/40_basic.t @@ -0,0 +1,277 @@ +# 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 => 35; + +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); + + +my $zkh = Net::ZooKeeper->new($hosts); +my $path; + +SKIP: { + my $ret = $zkh->exists($root_path) if (defined($zkh)); + + skip 'no connection to ZooKeeper', 1 unless + (defined($ret) and $ret); + + $path = $zkh->create($node_path, 'foo', 'acl' => ZOO_OPEN_ACL_UNSAFE); + is($path, $node_path, + 'create(): created node'); +} + +SKIP: { + skip 'no connection to ZooKeeper', 21 unless + (defined($path) and $path eq $node_path); + + + ## exists() + + my $ret = $zkh->exists($node_path); + ok($ret, + 'exists(): checked node existence'); + + $ret = $zkh->exists($node_path . '/NONE'); + ok((!$ret and $zkh->get_error() == ZNONODE and $! eq ''), + 'exists(): checked node non-existence'); + + my $stat = $zkh->stat(); + + $ret = $zkh->exists($node_path, 'stat' => $stat); + ok(($ret and $stat->{'data_len'} == 3), + 'exists(): checked node existence with stat handle'); + + + ## get() + + my $node = $zkh->get($node_path); + is($node, 'foo', + 'get(): retrieved node value'); + + $node = $zkh->get($node_path . '/NONE'); + ok((!defined($node) and $zkh->get_error() == ZNONODE and $! eq ''), + 'get(): undef returned for non-extant node'); + + $node = $zkh->get($node_path, 'data_read_len', 2); + is($node, 'fo', + 'get(): retrieved truncated node value'); + + $node = $zkh->get($node_path, 'data_read_len' => 0); + is($node, '', + 'get(): retrieved zero-length node value'); + + $node = $zkh->get($node_path, 'stat' => $stat); + ok(($node eq 'foo' and $stat->{'data_len'} == 3), + 'get(): retrieved node value with stat handle'); + + + ## set() + + $ret = $zkh->set($node_path, 'foo'); + ok($ret, + 'set(): set node value'); + + SKIP: { + my $ret = $zkh->exists($node_path, 'stat' => $stat); + + skip 'invalid node data', 2 unless + ($ret and $stat->{'version'} == 1); + + $ret = $zkh->set($node_path, 'foo', 'version' => $stat->{'version'}); + ok($ret, + 'set(): set node value with matching version'); + + $ret = $zkh->set($node_path, 'foo', 'version' => $stat->{'version'}); + ok((!$ret and $zkh->get_error() == ZBADVERSION and $! eq ''), + 'set(): node value unchanged if non-matching version'); + } + + $ret = $zkh->set($node_path, 'foobaz', 'stat' => $stat); + ok(($ret and $stat->{'data_len'} == 6), + 'set(): retrieved node value with stat handle'); + + + ## create(), delete() + + $path = $zkh->create($node_path, 'foo', 'acl' => ZOO_OPEN_ACL_UNSAFE); + ok((!defined($path) and $zkh->get_error() == ZNODEEXISTS and $! eq ''), + 'create(): undef when attempting to create extant node'); + + $ret = $zkh->delete($node_path . '/NONE'); + ok((!$ret and $zkh->get_error() == ZNONODE and $! eq ''), + 'delete(): no deletion of non-extant node'); + + $ret = $zkh->delete($node_path); + ok($ret, + 'delete(): deleted node'); + + my $path_read_len = length($node_path) - 2; + + $path = $zkh->create($node_path, 'foo', + 'path_read_len' => $path_read_len, + 'acl' => ZOO_OPEN_ACL_UNSAFE); + is($path, substr($node_path, 0, -2), + 'create(): created node with small return path buffer'); + + $path = $zkh->create("$node_path/s", 'foo', + 'flags' => ZOO_SEQUENCE, + 'acl' => ZOO_OPEN_ACL_UNSAFE); + like($path, qr/^$node_path\/s[0-9]+$/, + 'create(): created sequential node'); + + SKIP: { + my $ret = $zkh->exists($path, 'stat' => $stat); + + unless ($ret and $stat->{'version'} == 0) { + my $ret = $zkh->delete($path); + diag(sprintf('unable to delete node %s: %d, %s', + $path, $zkh->get_error(), $!)) unless ($ret); + + skip 'invalid node data', 2; + } + + $ret = $zkh->delete($path, 'version' => ($stat->{'version'} + 1)); + ok((!$ret and $zkh->get_error() == ZBADVERSION and $! eq ''), + 'delete(): node not deleted if non-matching version'); + + $ret = $zkh->delete($path, 'version' => $stat->{'version'}); + ok($ret, + 'delete(): deleted sequential node with matching version'); + } + + $path = $zkh->create("$node_path/e", 'foo', + 'flags' => ZOO_EPHEMERAL, + 'acl' => ZOO_OPEN_ACL_UNSAFE); + is($path, "$node_path/e", + 'create(): created ephemeral node'); + + $path = $zkh->create("$node_path/es", 'foo', + 'flags' => (ZOO_SEQUENCE | ZOO_EPHEMERAL), + 'acl' => ZOO_OPEN_ACL_UNSAFE); + like($path, qr/^$node_path\/es[0-9]+$/, + 'create(): created ephemeral sequential node'); + + undef $zkh; +} + +$zkh = Net::ZooKeeper->new($hosts); + +SKIP: { + my $ret = $zkh->exists($node_path) if (defined($zkh)); + + skip 'no connection to ZooKeeper', 12 unless + (defined($ret) and $ret); + + $ret = $zkh->exists("$node_path/e"); + ok((!$ret and $zkh->get_error() == ZNONODE and $! eq ''), + 'exists(): checked ephemeral node non-extant after reconnection'); + + $ret = $zkh->exists($path); + ok((!$ret and $zkh->get_error() == ZNONODE and $! eq ''), + 'exists(): checked ephemeral sequential node non-extant ' . + 'after reconnection'); + + + ## get_children() + + my @child_paths = ('abc'); + @child_paths = $zkh->get_children($node_path); + ok((@child_paths == 0 and $zkh->get_error() == ZOK), + 'get_children(): retrieved empty list of child nodes'); + + my $num_children = $zkh->get_children($node_path); + ok((defined($num_children) and $num_children == 0), + 'get_children(): retrieved zero count of child nodes'); + + @child_paths = $zkh->get_children($node_path . '/NONE'); + ok((@child_paths == 0 and $zkh->get_error() == ZNONODE and $! eq ''), + 'get_children(): empty list returned for non-extant node'); + + $num_children = $zkh->get_children($node_path . '/NONE'); + ok((!defined($num_children) and $zkh->get_error() == ZNONODE and $! eq ''), + 'get_children(): undef returned for non-extant node'); + + SKIP: { + my $path = $zkh->create("$node_path/c1", 'foo', + 'acl' => ZOO_OPEN_ACL_UNSAFE); + + skip 'no connection to ZooKeeper', 6 unless + (defined($path) and $path eq "$node_path/c1"); + + my @child_paths = ('abc'); + @child_paths = $zkh->get_children($node_path); + ok((@child_paths == 1 and $child_paths[0] eq 'c1'), + 'get_children(): retrieved list of single child node'); + + my $num_children = $zkh->get_children($node_path); + ok((defined($num_children) and $num_children == 1), + 'get_children(): retrieved count of single child node'); + + SKIP: { + my $path = $zkh->create("$node_path/c2", 'foo', + 'acl' => ZOO_OPEN_ACL_UNSAFE); + + skip 'no connection to ZooKeeper', 2 unless + (defined($path) and $path eq "$node_path/c2"); + + my @child_paths = ('abc'); + @child_paths = $zkh->get_children($node_path); + ok((@child_paths == 2 and $child_paths[0] eq 'c1' and + $child_paths[1] eq 'c2'), + 'get_children(): retrieved list of two child nodes'); + + my $num_children = $zkh->get_children($node_path); + ok((defined($num_children) and $num_children == 2), + 'get_children(): retrieved count of two child nodes'); + + my $ret = $zkh->delete("$node_path/c2"); + diag(sprintf('unable to delete node %s: %d, %s', + "$node_path/c2", $zkh->get_error(), $!)) unless + ($ret); + } + + @child_paths = ('abc'); + @child_paths = $zkh->get_children($node_path); + ok((@child_paths == 1 and $child_paths[0] eq 'c1'), + 'get_children(): retrieved list of single child node'); + + $num_children = $zkh->get_children($node_path); + ok((defined($num_children) and $num_children == 1), + 'get_children(): retrieved count of single child node'); + + my $ret = $zkh->delete("$node_path/c1"); + diag(sprintf('unable to delete node %s: %d, %s', + "$node_path/c1", $zkh->get_error(), $!)) unless ($ret); + } + + + ## cleanup + + $ret = $zkh->delete($node_path); + diag(sprintf('unable to delete node %s: %d, %s', + $node_path, $zkh->get_error(), $!)) unless ($ret); +} + http://git-wip-us.apache.org/repos/asf/zookeeper/blob/63aaf0a1/zookeeper-contrib/zookeeper-contrib-zkperl/t/45_class.t ---------------------------------------------------------------------- diff --git a/zookeeper-contrib/zookeeper-contrib-zkperl/t/45_class.t b/zookeeper-contrib/zookeeper-contrib-zkperl/t/45_class.t new file mode 100644 index 0000000..4aa1a57 --- /dev/null +++ b/zookeeper-contrib/zookeeper-contrib-zkperl/t/45_class.t @@ -0,0 +1,408 @@ +# 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 => 47; + +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); + + skip 'no valid handle', 15 unless (defined($zkh)); + + my $stat = $zkh->stat(); + my $watch = $zkh->watch(); + + + ## DESTROY() on reblessed handle + + bless($zkh, 'My::ZooKeeper'); + is(ref($zkh), 'My::ZooKeeper', + 'bless(): reblessed handle'); + + eval { + $zkh->EXISTS(); + }; + like($@, qr/Can't locate object method "EXISTS" via package "My::ZooKeeper"/, + 'EXISTS(): not defined on reblessed handle'); + + my $attr = tied(%{$zkh}); + + my $ret = $attr->DESTROY(); + ok($ret, + 'DESTROY(): destroyed inner hash of reblessed handle'); + + $ret = $attr->DESTROY(); + ok(!$ret, + 'DESTROY(): no action on destroyed inner hash of reblessed handle'); + + undef $zkh; + ok(!defined($zkh), + 'undef: released reblessed handle'); + + + ## DESTROY() on reblessed stat handle + + bless($stat, 'My::ZooKeeper::Stat'); + is(ref($stat), 'My::ZooKeeper::Stat', + 'bless(): reblessed stat handle'); + + eval { + $stat->EXISTS(1); + }; + like($@, qr/Can't locate object method "EXISTS" via package "My::ZooKeeper::Stat"/, + 'stat EXISTS(): not defined on reblessed stat handle'); + + $attr = tied(%{$stat}); + + $ret = $attr->DESTROY(); + ok($ret, + 'stat DESTROY(): destroyed inner hash of reblessed stat handle'); + + $ret = $attr->DESTROY(); + ok(!$ret, + 'stat DESTROY(): no action on destroyed inner hash of ' . + 'reblessed stat handle'); + + undef $stat; + ok(!defined($stat), + 'undef: released reblessed stat handle'); + + + ## DESTROY() on reblessed watch handle + + bless($watch, 'My::ZooKeeper::Watch'); + is(ref($watch), 'My::ZooKeeper::Watch', + 'bless(): reblessed watch handle'); + + eval { + $watch->EXISTS(1); + }; + like($@, qr/Can't locate object method "EXISTS" via package "My::ZooKeeper::Watch"/, + 'watch EXISTS(): not defined on reblessed watch handle'); + + $attr = tied(%{$watch}); + + $ret = $attr->DESTROY(); + ok($ret, + 'watch DESTROY(): destroyed inner hash of reblessed watch handle'); + + $ret = $attr->DESTROY(); + ok(!$ret, + 'watch DESTROY(): no action on destroyed inner hash of ' . + 'reblessed watch handle'); + + undef $watch; + ok(!defined($watch), + 'undef: released reblessed watch handle'); +} + +SKIP: { + my $zkh = Net::ZooKeeper->new($hosts); + + skip 'no valid handle', 9 unless (defined($zkh)); + + my $stat = $zkh->stat(); + my $watch = $zkh->watch(); + + + ## UNTIE() on reblessed handle + + bless($zkh, 'My::ZooKeeper'); + is(ref($zkh), 'My::ZooKeeper', + 'bless(): reblessed handle'); + + eval { + untie(%{$zkh}); + }; + like($@, qr/untying hashes of class Net::ZooKeeper not supported/, + 'untie(): untying hashes from reblessed handle not supported'); + + my $attr = tied(%{$zkh}); + + eval { + $attr->UNTIE(0); + }; + like($@, qr/untying hashes of class Net::ZooKeeper not supported/, + 'UNTIE(): untying hashes from reblessed handle not supported'); + + + ## UNTIE() on reblessed stat handle + + bless($stat, 'My::ZooKeeper::Stat'); + is(ref($stat), 'My::ZooKeeper::Stat', + 'bless(): reblessed stat handle'); + + eval { + untie(%{$stat}); + }; + like($@, qr/untying hashes of class Net::ZooKeeper::Stat not supported/, + 'untie(): untying hashes from reblessed stat handle not supported'); + + $attr = tied(%{$stat}); + + eval { + $attr->UNTIE(0); + }; + like($@, qr/untying hashes of class Net::ZooKeeper::Stat not supported/, + 'stat UNTIE(): untying hashes from reblessed stat handle ' . + 'not supported'); + + + ## UNTIE() on reblessed watch handle + + bless($watch, 'My::ZooKeeper::Watch'); + is(ref($watch), 'My::ZooKeeper::Watch', + 'bless(): reblessed watch handle'); + + eval { + untie(%{$watch}); + }; + like($@, qr/untying hashes of class Net::ZooKeeper::Watch not supported/, + 'untie(): untying hashes from reblessed watch handle not supported'); + + $attr = tied(%{$watch}); + + eval { + $attr->UNTIE(0); + }; + like($@, qr/untying hashes of class Net::ZooKeeper::Watch not supported/, + 'watch UNTIE(): untying hashes from reblessed watch handle ' . + 'not supported'); +} + + +package Net::ZooKeeper::Test; + +use Net::ZooKeeper qw(:acls); + +our @ISA = qw(Net::ZooKeeper); + +sub create +{ + my($self, $path, $buf) = @_; + + return $self->SUPER::create($path, $buf, + 'path_read_len' => length($path), + 'acl' => ZOO_OPEN_ACL_UNSAFE); +} + +sub get_first_child +{ + my($self, $path) = @_; + + my @child_paths = $self->get_children($path); + + if (@child_paths > 0) { + return $path . (($path =~ /\/$/) ? '' : '/') . $child_paths[0]; + } + + return undef; +} + +sub stat +{ + my $self = shift; + + my $stat = $self->SUPER::stat(); + + return bless($stat, 'Net::ZooKeeper::Test::Stat'); +} + + +sub watch +{ + my $self = shift; + + my $watch = $self->SUPER::watch(); + + return bless($watch, 'Net::ZooKeeper::Test::Watch'); +} + + +package Net::ZooKeeper::Test::Stat; + +our @ISA = qw(Net::ZooKeeper::Stat); + +sub get_ctime +{ + my $self = shift; + + return $self->{'ctime'}; +} + + +package Net::ZooKeeper::Test::Watch; + +our @ISA = qw(Net::ZooKeeper::Watch); + +sub get_timeout +{ + my $self = shift; + + return $self->{'timeout'}; +} + + +package main; + +my $sub_zkh = Net::ZooKeeper::Test->new($hosts); +isa_ok($sub_zkh, 'Net::ZooKeeper::Test', + 'new(): created subclassed handle'); + +SKIP: { + skip 'no valid subclassed handle', 21 unless (defined($sub_zkh)); + + is($sub_zkh->{'data_read_len'}, 1023, + 'FETCH(): default data read length using subclassed handle'); + + my $path; + + SKIP: { + my $ret = $sub_zkh->exists($root_path); + + skip 'no connection to ZooKeeper', 1 unless + (defined($ret) and $ret); + + $path = $sub_zkh->create($node_path, 'foo', + 'acl' => ZOO_OPEN_ACL_UNSAFE); + is($path, $node_path, + 'create(): created node with subclassed handle'); + } + + SKIP: { + skip 'no connection to ZooKeeper', 1 unless + (defined($path) and $path eq $node_path); + + my $child_path = $sub_zkh->get_first_child($root_path); + is($child_path, $node_path, + 'get_first_child(): retrieved first child with subclassed handle'); + } + + my $sub_stat = $sub_zkh->stat(); + isa_ok($sub_stat, 'Net::ZooKeeper::Test::Stat', + 'stat(): created subclassed stat handle'); + + SKIP: { + skip 'no valid subclassed stat handle', 6 unless + (defined($sub_stat)); + + is($sub_stat->{'ctime'}, 0, + 'stat FETCH(): default ctime using subclassed stat handle'); + + SKIP: { + my $ret = $sub_zkh->exists($node_path, 'stat' => $sub_stat) if + (defined($path) and $path eq $node_path); + + skip 'no connection to ZooKeeper', 2 unless + (defined($ret) and $ret); + + my $ctime = $sub_stat->get_ctime(); + ok($ctime > 0, + 'get_ctime(): retrieved ctime with subclassed stat handle'); + + is($sub_stat->{'ctime'}, $ctime, + 'stat FETCH(): ctime using subclassed stat handle'); + } + + my $ret = $sub_stat->DESTROY(); + ok($ret, + 'stat DESTROY(): destroyed subclassed stat handle'); + + $ret = $sub_stat->DESTROY(); + ok(!$ret, + 'stat DESTROY(): no action on destroyed subclassed stat handle'); + + undef $sub_stat; + ok(!defined($sub_stat), + 'undef: released subclassed stat handle'); + } + + my $sub_watch = $sub_zkh->watch(); + isa_ok($sub_watch, 'Net::ZooKeeper::Test::Watch', + 'watch(): created subclassed watch handle'); + + SKIP: { + skip 'no valid subclassed watch handle', 6 unless + (defined($sub_watch)); + + SKIP: { + my $ret = $sub_zkh->exists($root_path, 'watch' => $sub_watch); + + skip 'no connection to ZooKeeper', 3 unless + (defined($ret) and $ret); + + $sub_watch->{'timeout'} = 50; + + is($sub_watch->get_timeout(), 50, + 'get_timeout(): retrieved timeout with subclassed ' . + 'watch handle'); + + is($sub_watch->{'timeout'}, 50, + 'watch FETCH(): timeout using subclassed stat handle'); + + $ret = $sub_watch->wait(); + ok(!$ret, + 'wait(): watch after checking node existence timed out with ' . + 'subclassed watch handle'); + } + + my $ret = $sub_watch->DESTROY(); + ok($ret, + 'watch DESTROY(): destroyed subclassed watch handle'); + + $ret = $sub_watch->DESTROY(); + ok(!$ret, + 'watch DESTROY(): no action on destroyed subclassed watch handle'); + + undef $sub_watch; + ok(!defined($sub_watch), + 'undef: released subclassed watch handle'); + } + + SKIP: { + skip 'no connection to ZooKeeper', 1 unless + (defined($path) and $path eq $node_path); + + my $ret = $sub_zkh->delete($node_path); + ok($ret, + 'delete(): deleted node with subclassed handle'); + } + + my $ret = $sub_zkh->DESTROY(); + ok($ret, + 'DESTROY(): destroyed subclassed handle'); + + $ret = $sub_zkh->DESTROY(); + ok(!$ret, + 'DESTROY(): no action on destroyed subclassed handle'); + + undef $sub_zkh; + ok(!defined($sub_zkh), + 'undef: released subclassed handle'); +} +
