App-FuguVM
view release on metacpan or search on metacpan
t/fuguvm/guest.t view on Meta::CPAN
state => $fleet_state,
log => TestLog->new,
);
is($fleet->_resolve_ports, undef, '_resolve_ports resolves auto');
my $resolved = $fleet_state->get_runtime;
ok($resolved->{ssh_port} >= 2222 && $resolved->{ssh_port} <= 2321,
'auto takes a port of the SSH range');
isnt($resolved->{ssh_port}, 2222,
'and skips the port that a sibling records');
ok($resolved->{console_port} >= 4444
&& $resolved->{console_port} <= 4543,
'auto takes a port of the console range');
isnt($resolved->{console_port}, 4444,
'and skips the console port of the sibling');
$fleet_state->vm_pidfile->write_pid($$);
is($fleet->ssh_port, $resolved->{ssh_port},
'ssh_port returns the recorded port of the running guest');
$fleet_state->clear_vm_pid;
# A probe must not select the fixed port of the other directive
# of the same guest, and must not select a fixed port of a
# declared sibling
my $mixed_state = App::FuguVM::State->new("$root/state", 'mixed');
my $mixed = App::FuguVM::Guest->new(
config => { name => 'mixed', arch => 'arm64',
ssh_port => 'auto', console_port => 2223,
declared_ports => { 2224 => 1 },
cache_dir => "$root/cache" },
state => $mixed_state,
log => TestLog->new,
);
is($mixed->_resolve_ports, undef,
'_resolve_ports resolves a mixed declaration');
my $mixed_ports = $mixed_state->get_runtime;
isnt($mixed_ports->{ssh_port}, 2223,
'auto skips the fixed port of the other directive');
isnt($mixed_ports->{ssh_port}, 2224,
'auto skips a declared fixed port of the project');
is($mixed_ports->{console_port}, 2223,
'and the fixed port resolves to itself');
# An exhausted range is a diagnosed failure, not a hang. No
# host interface holds the documentation address, so no port
# of the range binds.
my $dead_state = App::FuguVM::State->new("$root/state", 'dead');
my $dead = App::FuguVM::Guest->new(
config => { name => 'dead', arch => 'arm64',
ssh_port => 'auto', console_port => 'auto',
bind_address => '192.0.2.1',
cache_dir => "$root/cache" },
state => $dead_state,
log => TestLog->new,
);
is($dead->_resolve_ports, App::FuguVM::Guest::EXIT_ERROR(),
'an exhausted range gives EXIT_ERROR');
like(join("\n", @{ $dead->{log}{errors} }), qr/2222-2321/,
'and the message names the range');
# The port lock is exclusive across processes
my $locked = $fleet->_lock_ports;
ok(defined $locked, '_lock_ports returns a handle');
is(_flock_in_child("$root/cache/ports.lock"), 0,
'a child cannot take the held lock');
close $locked;
is(_flock_in_child("$root/cache/ports.lock"), 1,
'the lock is free once the handle closes');
}
# The accelerator answer: the record wins for a running guest, and
# the current selection serves a stopped one
{
require App::FuguVM::State;
my $root = tempdir(CLEANUP => 1);
my $state = App::FuguVM::State->new("$root/state", 'default');
my $vm = App::FuguVM::Guest->new(
config => { name => 'default', arch => 'arm64' },
state => $state,
);
like($vm->accel, qr/^(hvf|kvm|tcg)$/,
'accel returns a known name for a stopped guest');
$state->set_runtime(
accel => 'kvm', ssh_port => 2222, console_port => 4444);
$state->vm_pidfile->write_pid($$);
is($vm->accel, 'kvm', 'accel returns the recorded value while running');
$state->clear_vm_pid;
my $emulated = App::FuguVM::Guest->new(
config => { name => 'default', arch => 'arm64' },
state => $state,
emulate => 1,
);
is($emulated->accel, 'tcg', '--emulate selects TCG for a stopped guest');
}
# The QEMU network and serial arguments carry the bind address and
# the recorded ports. This assembly enforces the loopback default.
{
require App::FuguVM::State;
my $root = tempdir(CLEANUP => 1);
my $state = App::FuguVM::State->new("$root/state", 'default');
$state->set_runtime(
accel => 'tcg', ssh_port => 2299, console_port => 4499);
my $vm = App::FuguVM::Guest->new(
config => { name => 'default', arch => 'arm64',
bind_address => '127.0.0.1' },
state => $state,
);
is(($vm->_network_args)[3],
'user,id=net0,hostfwd=tcp:127.0.0.1:2299-:22',
'the hostfwd rule carries the bind address and the SSH port');
is(($vm->_serial_args)[1],
'tcp:127.0.0.1:4499,server,telnet,nowait',
'the serial listener carries the bind address and the port');
my $open = App::FuguVM::Guest->new(
config => { name => 'default', arch => 'arm64',
bind_address => '0.0.0.0' },
state => $state,
);
( run in 0.706 second using v1.01-cache-2.11-cpan-800906f7e73 )