From e10620c02fa849c43209436ddd5dc0803839f4c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Ferr=C3=A3o?= <2031761+viniciusferrao@users.noreply.github.com> Date: Tue, 25 Aug 2026 18:34:15 -0300 Subject: [PATCH] test(rspconfig): prepare direct helper loading --- xCAT-test/unit/rspconfig_per_bmc_argument.t | 90 ++++++++++++++------- 1 file changed, 63 insertions(+), 27 deletions(-) diff --git a/xCAT-test/unit/rspconfig_per_bmc_argument.t b/xCAT-test/unit/rspconfig_per_bmc_argument.t index 51b9bc0c0..cf9ff6a5e 100644 --- a/xCAT-test/unit/rspconfig_per_bmc_argument.t +++ b/xCAT-test/unit/rspconfig_per_bmc_argument.t @@ -6,25 +6,61 @@ use FindBin; use File::Spec; use Test::More; -my $plugin = File::Spec->catfile( $FindBin::Bin, '..', '..', +my $root = File::Spec->catdir( $FindBin::Bin, '..', '..' ); +my $plugin = File::Spec->catfile( $root, '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); +my $lib = File::Spec->catdir( $root, 'xCAT-server', 'lib', 'perl' ); +my $module = File::Spec->catfile( $lib, 'xCAT', 'BMCUtils.pm' ); +my $direct_module = -r $module; +my ( $source, $per_bmc ); -# 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: $@"); +if ($direct_module) { + unshift @INC, $lib; + require xCAT::BMCUtils; +} else { + open( my $fh, '<', $plugin ) or die "Unable to read $plugin: $!"; + $source = do { local $/; <$fh> }; + close($fh); -sub pick { return BmcArg::per_bmc_argument(@_); } -my $per_bmc = BmcArg::gate(); + 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: $@"); + $per_bmc = BmcArg::gate(); +} + +sub setting { + my ( $subcommand, $argument, $bmcnum ) = @_; + if ($direct_module) { + return xCAT::BMCUtils::rspconfig_bmc_setting( + $subcommand, $argument, $bmcnum ); + } + return { argument => $argument } + unless $per_bmc->{$subcommand} and defined $argument and $argument =~ /,/; + my $value = BmcArg::per_bmc_argument( $argument, $bmcnum ); + return { error => 1 } unless defined $value; + return { + argument => $value, + session_subcommand => "$subcommand=$value", + }; +} + +sub pick { + my ( $argument, $bmcnum ) = @_; + return setting( 'ip', $argument, $bmcnum )->{argument}; +} + +if ($direct_module) { + $per_bmc = {}; + foreach my $subcommand (qw(ip netmask gateway community snmpdest alert garp thermprofile)) { + my $selection = setting( $subcommand, 'first,second', 1 ); + $per_bmc->{$subcommand} = exists $selection->{session_subcommand}; + } +} # A single value reaches every BMC, which is what a node with one BMC needs # and what every existing command line looks like. @@ -59,20 +95,20 @@ is( pick( '255.255.255.0,255.255.254.0', 2 ), '255.255.254.0', 'a netmask list f 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' ); +unless ($direct_module) { + 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 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' ); + 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();