305 lines
8.9 KiB
Perl
305 lines
8.9 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 => 30;
|
|
|
|
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 $path = $zkh->create($node_path, 'foo',
|
|
'acl' => ZOO_OPEN_ACL_UNSAFE) if (defined($zkh));
|
|
|
|
skip 'no connection to ZooKeeper', 20 unless
|
|
(defined($path) and $path eq $node_path);
|
|
|
|
|
|
## exists()
|
|
|
|
$zkh->{'watch_timeout'} = 100;
|
|
|
|
my $watch = $zkh->watch();
|
|
|
|
my $ret = $zkh->exists($node_path, 'watch' => $watch);
|
|
ok($ret,
|
|
'exists(): checked node existence with watch handle');
|
|
|
|
$ret = $watch->wait();
|
|
ok(!$ret,
|
|
'wait(): watch after checking node existence timed out');
|
|
|
|
$ret = $zkh->exists($node_path, 'watch' => $watch);
|
|
ok($ret,
|
|
'exists(): checked node existence with renewed watch handle');
|
|
|
|
$ret = $watch->wait();
|
|
ok(!$ret,
|
|
'wait(): watch after checking node existence timed out with ' .
|
|
'renewed watch handle');
|
|
|
|
undef $watch;
|
|
ok(!defined($watch),
|
|
'undef: released watch handle');
|
|
|
|
my $pending_watches = $zkh->{'pending_watches'};
|
|
is($pending_watches, 2,
|
|
'_zk_release_watches(): report pending watches');
|
|
|
|
|
|
## get_children()
|
|
|
|
$watch = $zkh->watch('timeout' => 50);
|
|
|
|
my $num_children = $zkh->get_children($node_path, 'watch' => $watch);
|
|
ok((defined($num_children) and $num_children == 0),
|
|
'get_children(): retrieved zero count of child nodes with ' .
|
|
'watch handle');
|
|
|
|
$ret = $watch->wait();
|
|
ok(!$ret,
|
|
'wait(): watch after retrieving child nodes timed out with ' .
|
|
'watch handle');
|
|
|
|
$watch->{'timeout'} = 100;
|
|
|
|
my @child_paths = $zkh->get_children($node_path, 'watch' => $watch);
|
|
ok((@child_paths == 0),
|
|
'get_children(): retrieved empty list of child nodes with ' .
|
|
'renewed watch handle');
|
|
|
|
$ret = $watch->wait();
|
|
ok(!$ret,
|
|
'wait(): watch after retrieving child nodes timed out with ' .
|
|
'renewed watch handle');
|
|
|
|
$pending_watches = $zkh->{'pending_watches'};
|
|
is($pending_watches, 4,
|
|
'_zk_release_watches(): report pending watches');
|
|
|
|
|
|
## get()
|
|
|
|
$watch = $zkh->watch();
|
|
|
|
my $node = $zkh->get($node_path, 'watch' => $watch);
|
|
is($node, 'foo',
|
|
'get(): retrieved node value with watch handle');
|
|
|
|
$ret = $watch->wait('timeout' => 0);
|
|
ok(!$ret,
|
|
'wait(): watch after retrieving node value timed out with ' .
|
|
'watch handle');
|
|
|
|
$node = $zkh->get($node_path, 'watch' => $watch);
|
|
is($node, 'foo',
|
|
'get(): retrieved node value with renewed watch handle');
|
|
|
|
$ret = $watch->wait();
|
|
ok(!$ret,
|
|
'wait(): watch after retrieving node value timed out with ' .
|
|
'renewed watch handle');
|
|
|
|
$pending_watches = $zkh->{'pending_watches'};
|
|
is($pending_watches, 6,
|
|
'_zk_release_watches(): all watches pending');
|
|
|
|
|
|
## _zk_release_watches()
|
|
|
|
$ret = $zkh->DESTROY();
|
|
ok($ret,
|
|
'DESTROY(): destroyed handle with pending watches');
|
|
|
|
my $event = $watch->{'event'};
|
|
is($event, 0,
|
|
'_zk_release_watches(): watch not destroyed when tied to watch handle');
|
|
|
|
$zkh = Net::ZooKeeper->new($hosts);
|
|
|
|
SKIP: {
|
|
my $ret = $zkh->exists($node_path, 'watch' => $watch);
|
|
|
|
skip 'no connection to ZooKeeper', 2 unless
|
|
(defined($ret) and $ret);
|
|
|
|
ok($ret,
|
|
'exists(): checked node existence with renewed watch handle ' .
|
|
'from prior connection');
|
|
|
|
$ret = $watch->wait();
|
|
ok(!$ret,
|
|
'wait(): watch after checking node existence timed out with ' .
|
|
'renewed watch handle from prior connection');
|
|
|
|
|
|
}
|
|
}
|
|
|
|
my $pid = fork();
|
|
|
|
SKIP: {
|
|
skip 'unable to fork', 4 unless (defined($pid));
|
|
|
|
my $zkh = Net::ZooKeeper->new($hosts);
|
|
|
|
my $ret = $zkh->exists($node_path) if (defined($zkh));
|
|
|
|
if ($pid == 0) {
|
|
## child process
|
|
|
|
my $code = 0;
|
|
|
|
if (defined($ret) and $ret) {
|
|
sleep(1);
|
|
|
|
my $ret = $zkh->set($node_path, 'foo');
|
|
|
|
diag(sprintf('set(): failed in child process: %d, %s',
|
|
$zkh->get_error(), $!)) unless ($ret);
|
|
|
|
$code = !$ret;
|
|
|
|
sleep(1);
|
|
|
|
my $path = $zkh->create("$node_path/c", 'foo',
|
|
'acl' => ZOO_OPEN_ACL_UNSAFE);
|
|
|
|
diag(sprintf('create(): failed in child process: %d, %s',
|
|
$zkh->get_error(), $!)) unless
|
|
(defined($path) and $path eq "$node_path/c");
|
|
|
|
$code &= !$ret;
|
|
|
|
sleep(1);
|
|
|
|
$ret = $zkh->delete("$node_path/c");
|
|
|
|
diag(sprintf('delete(): failed in child process: %d, %s',
|
|
$zkh->get_error(), $!)) unless ($ret);
|
|
|
|
$code &= !$ret;
|
|
|
|
sleep(1);
|
|
|
|
$ret = $zkh->set($node_path, 'foo');
|
|
|
|
diag(sprintf('set(): failed in child process: %d, %s',
|
|
$zkh->get_error(), $!)) unless ($ret);
|
|
|
|
$code &= !$ret;
|
|
}
|
|
|
|
exit($code);
|
|
}
|
|
else {
|
|
## parent process
|
|
|
|
SKIP: {
|
|
skip 'no connection to ZooKeeper', 9 unless
|
|
(defined($ret) and $ret);
|
|
|
|
my $watch = $zkh->watch('timeout' => 5000);
|
|
|
|
|
|
## wait()
|
|
|
|
my $ret = $zkh->exists($node_path, 'watch' => $watch);
|
|
ok($ret,
|
|
'exists(): checked node existence with watch handle ' .
|
|
'in parent');
|
|
|
|
$ret = $watch->wait();
|
|
ok(($ret and $watch->{'event'} == ZOO_CHANGED_EVENT and
|
|
$watch->{'state'} == ZOO_CONNECTED_STATE),
|
|
'wait(): waited for event after checking node existence');
|
|
|
|
my $num_children = $zkh->get_children($node_path,
|
|
'watch' => $watch);
|
|
ok((defined($num_children) and $num_children == 0),
|
|
'get_children(): retrieved zero count of child nodes with ' .
|
|
'watch handle in parent');
|
|
|
|
$ret = $watch->wait();
|
|
ok(($ret and $watch->{'event'} == ZOO_CHILD_EVENT and
|
|
$watch->{'state'} == ZOO_CONNECTED_STATE),
|
|
'wait(): waited for create child event after ' .
|
|
'retrieving child nodes');
|
|
|
|
my @child_paths = $zkh->get_children($node_path,
|
|
'watch' => $watch);
|
|
ok((@child_paths == 1 and $child_paths[0] eq 'c'),
|
|
'get_children(): retrieved list of child nodes with ' .
|
|
'watch handle in parent');
|
|
|
|
$ret = $watch->wait();
|
|
ok(($ret and $watch->{'event'} == ZOO_CHILD_EVENT and
|
|
$watch->{'state'} == ZOO_CONNECTED_STATE),
|
|
'wait(): waited for delete child event after ' .
|
|
'retrieving child nodes');
|
|
|
|
my $node = $zkh->get($node_path, 'watch' => $watch);
|
|
is($node, 'foo',
|
|
'get(): retrieved node value with watch handle in parent');
|
|
|
|
$ret = $watch->wait();
|
|
ok(($ret and $watch->{'event'} == ZOO_CHANGED_EVENT and
|
|
$watch->{'state'} == ZOO_CONNECTED_STATE),
|
|
'wait(): waited for event after retrieving node value');
|
|
|
|
undef $watch;
|
|
|
|
my $pending_watches = $zkh->{'pending_watches'};
|
|
is($pending_watches, 0,
|
|
'_zk_release_watches(): no watches pending');
|
|
}
|
|
|
|
my $reap = waitpid($pid, 0);
|
|
|
|
diag(sprintf('child process failed: exit %d, signal %d%s',
|
|
($? >> 8), ($? & 127),
|
|
(($? & 128) ? ', core dump' : ''))) if
|
|
($reap == $pid and $? != 0);
|
|
}
|
|
}
|
|
|
|
|
|
## cleanup
|
|
|
|
{
|
|
my $zkh = Net::ZooKeeper->new($hosts);
|
|
|
|
my $ret = $zkh->exists($node_path) if (defined($zkh));
|
|
|
|
if (defined($ret) and $ret) {
|
|
$ret = $zkh->delete($node_path);
|
|
diag(sprintf('unable to delete node %s: %d, %s',
|
|
$node_path, $zkh->get_error(), $!)) unless ($ret);
|
|
}
|
|
}
|
|
|