2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2026-10-20 14:45:41 +00:00

test(rspconfig): cover one network value per BMC

Extract per_bmc_argument and the set of settings that take a list from
ipmi.pm, and drive the real routine, because the plugin needs daemon
dependencies that the test host does not have.

Cover a single value serving every BMC, a list read in session order, a
list too short for the BMC being configured, empty entries, and the
defensive inputs. Assert that only ip, netmask and gateway read a list,
that the caller reports a short list rather than sending it, that the
session keeps the value of its own BMC for the follow-up, and that the
thermal profile keeps its own argument.
This commit is contained in:
Vinícius Ferrão
2026-08-21 02:49:03 -03:00
parent f9ed90ec0b
commit 8a64b224a3
@@ -0,0 +1,78 @@
#!/usr/bin/env perl
use strict;
use warnings;
use FindBin;
use File::Spec;
use Test::More;
my $plugin = File::Spec->catfile( $FindBin::Bin, '..', '..',
'xCAT-server', 'lib', 'xcat', 'plugins', 'ipmi.pm' );
plan skip_all => 'ipmi.pm not found' unless -r $plugin;
open( my $fh, '<', $plugin ) or die "Unable to read $plugin: $!";
my $source = do { local $/; <$fh> };
close($fh);
# ipmi.pm cannot be loaded here, so lift out the routine and drive the real
# code on its own.
my ($routine) = $source =~ /(sub per_bmc_argument \{.*?\n\}\n)/s;
my ($gate) = $source =~ /(my %per_bmc_subcommand = map.*?;)/s;
BAIL_OUT('could not extract per_bmc_argument from ipmi.pm') unless $routine;
BAIL_OUT('could not extract the per BMC subcommand set from ipmi.pm') unless $gate;
eval "package BmcArg; $gate $routine sub gate { return \\%per_bmc_subcommand } 1;"
or BAIL_OUT("could not evaluate per_bmc_argument: $@");
sub pick { return BmcArg::per_bmc_argument(@_); }
my $per_bmc = BmcArg::gate();
# A single value reaches every BMC, which is what a node with one BMC needs
# and what every existing command line looks like.
is( pick( '10.0.0.5', 1 ), '10.0.0.5', 'a single value serves the first BMC' );
is( pick( '10.0.0.5', 2 ), '10.0.0.5', 'a single value serves a later BMC too' );
# A list gives one setting per BMC, in session order.
is( pick( '10.0.0.5,10.0.0.6', 1 ), '10.0.0.5', 'the first BMC takes the first value' );
is( pick( '10.0.0.5,10.0.0.6', 2 ), '10.0.0.6', 'the second BMC takes the second value' );
is( pick( '10.0.0.5,10.0.0.6,10.0.0.7', 3 ), '10.0.0.7', 'the third BMC takes the third value' );
# A list too short reports nothing rather than an empty setting, so the caller
# can tell the operator instead of writing a blank value into a BMC.
is( pick( '10.0.0.5,10.0.0.6', 3 ), undef, 'a list shorter than the BMC number yields nothing' );
# An empty element carries no setting, so it reads as missing rather than
# reaching the address encoders, which reject an empty string outright.
is( pick( '10.0.0.5,', 2 ), undef, 'an empty element yields nothing' );
is( pick( ',10.0.0.6', 1 ), undef, 'a leading empty element yields nothing' );
# Defensive input.
is( pick( undef, 1 ), undef, 'an undefined argument stays undefined' );
is( pick( '10.0.0.5,10.0.0.6' ), '10.0.0.5', 'a missing BMC number reads as the first' );
is( pick( '10.0.0.5,10.0.0.6', 0 ), '10.0.0.5', 'a zero BMC number reads as the first' );
# The netmask and gateway settings travel the same path.
is( pick( '255.255.255.0,255.255.254.0', 2 ), '255.255.254.0', 'a netmask list follows the BMC number' );
# Only the settings the man page advertises take a list. Every other
# subcommand keeps its argument whole, because a comma can belong to the value,
# as it does in a free form SNMP community string.
ok( $per_bmc->{$_}, "$_ takes one value per BMC" ) for qw(ip netmask gateway);
ok( !$per_bmc->{$_}, "$_ keeps its argument whole" ) for qw(community snmpdest alert garp thermprofile);
like( $source, qr/if \(\$per_bmc_subcommand\{\$subcommand\} and \$argument =~ \/,\/\)/,
'the caller splits only the settings that take a list' );
# The follow-up callbacks read the subcommand again, so the session has to hold
# the value of its own BMC by then.
like( $source, qr/\$sessdata->\{subcommand\} = "\$subcommand=\$argument";/,
'the session keeps the value of its own BMC for the follow-up' );
# The caller reports the mismatch rather than sending an empty setting, and
# the thermal profile keeps its own argument.
like( $source,
qr/unless \(defined \$bmcvalue\) \{\s*\n\s*\$callback->\(\{ errorcode => \[1\], error => \["The value \$argument does not carry a setting for BMC/,
'the caller reports a short list instead of sending it' );
like( $source, qr/if \(\$subcommand eq "thermprofile"\) \{\n\s*return idpxthermprofile\(\$argument\);/,
'the thermal profile is answered before the per BMC split' );
done_testing();