EV-Websockets
view release on metacpan or search on metacpan
t/27-review-coverage.t view on Meta::CPAN
my $to = EV::timer(10, 0, sub { diag "Timeout!"; EV::break });
EV::run;
ok($got101, "raw client got a 101 response");
ok($found, "static listen(headers => ...) injected into 101 response");
}
# 5. on_drain does NOT fire once close() has been queued.
{
my $ctx = EV::Websockets::Context->new();
my %keep;
my ($drain_after_close, $closed) = (0, 0);
my $port = $ctx->listen(
port => 0,
on_connect => sub { $keep{srv} = $_[0] },
on_message => sub { },
on_close => sub { delete $keep{srv} },
);
$keep{cli} = $ctx->connect(
url => "ws://127.0.0.1:$port",
on_connect => sub {
my ($c) = @_;
$c->send("x" x 1024) for 1 .. 5; # queue payload
$c->close(1000); # then start closing
},
on_drain => sub { $drain_after_close = 1 },
on_message => sub { },
on_close => sub {
$closed = 1; delete $keep{cli};
my $t; $t = EV::timer(0.3, 0, sub { undef $t; EV::break });
},
on_error => sub { delete $keep{cli}; EV::break },
);
my $to = EV::timer(10, 0, sub { diag "Timeout!"; EV::break });
EV::run;
ok($closed, "connection closed after queue + close()");
ok(!$drain_after_close, "on_drain suppressed once close() was queued");
}
# 6a. listen() reserved-name guard croaks and cleans up its callback SVs.
{
my $ctx = EV::Websockets::Context->new();
my $ok = eval {
$ctx->listen(port => 0, name => 'default', on_message => sub { });
1;
};
ok(!$ok, "listen(name => 'default') croaked");
like($@, qr/reserved/i, "croak says the name is reserved");
}
# NOTE: the listen() bind-failure (RETVAL <= 0) path isn't driven here:
# colliding on an explicit port is unreliable under SO_REUSEPORT (the bind
# succeeds, and a 2-vhost-same-port context tickles an lws-internal teardown
# read). The vhost-creation-failure path (free_server_svs) is exercised by an
# unreadable-TLS-cert listen in t/28 (fork-contained) -- that path once
# SIGSEGV'd via OpenSSL's ERR path after a context had been destroyed, but the
# SSL keepalive fix resolved it. free_server_svs also runs on every successful
# listen() teardown via PROTOCOL_DESTROY.
# 7. Saving $conn inside on_error then dropping it must not crash.
# Exercises the connect() failure path where perl_self is set during a
# (possibly synchronous) connection error.
{
my $ctx = EV::Websockets::Context->new();
my $saved;
my $err = 0;
{
my %keep;
$keep{cli} = $ctx->connect(
url => "ws://127.0.0.1:1",
on_connect => sub { },
on_error => sub { $saved = $_[0]; $err++; EV::break },
);
my $to = EV::timer(5, 0, sub { diag "Timeout!"; EV::break });
EV::run;
}
ok($err, "on_error fired for refused connection");
isa_ok($saved, 'EV::Websockets::Connection', "conn captured in on_error");
is($saved->state, 'closed', "captured conn reports 'closed'");
is($saved->send_queue_size, 0, "send_queue_size is 0 on closed conn (no croak)");
$saved = undef; # drop the last reference -> DESTROY
pass("no crash after dropping the saved conn reference");
}
# 8. send_queue_size returns 0 (no croak) after the context is destroyed.
{
my $conn;
{
my $ctx = EV::Websockets::Context->new();
my %keep;
my $port = $ctx->listen(
port => 0,
on_connect => sub { $keep{srv} = $_[0] },
on_message => sub { },
on_close => sub { delete $keep{srv} },
);
$keep{cli} = $ctx->connect(
url => "ws://127.0.0.1:$port",
on_connect => sub { $conn = $_[0]; EV::break },
on_error => sub { EV::break },
);
my $to = EV::timer(10, 0, sub { diag "Timeout!"; EV::break });
EV::run;
# $ctx and %keep drop here -> Context::DESTROY -> conn becomes "closed"
}
ok($conn, "captured a live connection");
is($conn->state, 'closed', "conn is 'closed' after context destroyed");
is($conn->send_queue_size, 0, "send_queue_size returns 0 on closed conn");
$conn = undef;
}
# 9. connections() excludes a still-connecting conn, includes it once open.
# (get_protocol, peer_address and send_queue_size>0 happy paths are already
# covered by t/18 and t/24; only the connecting-exclusion is untested.)
( run in 1.840 second using v1.01-cache-2.11-cpan-14f38c9f855 )