2021-10-19 15:30:39 +08:00

409 lines
10 KiB
Perl

# 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');
}