diff --git a/build-ubunturepo b/build-ubunturepo index bc92165ee..8a36a17e4 100755 --- a/build-ubunturepo +++ b/build-ubunturepo @@ -363,6 +363,7 @@ then #3 symbolic link can't work during package if [ $file_low = "xcat-probe" ]; then mkdir -p ${CURDIR}/lib/perl/xCAT/ + cp -f ${CURDIR}/../perl-xCAT/xCAT/CommandUtils.pm ${CURDIR}/lib/perl/xCAT/ cp -f ${CURDIR}/../perl-xCAT/xCAT/NetworkUtils.pm ${CURDIR}/lib/perl/xCAT/ cp -f ${CURDIR}/../perl-xCAT/xCAT/GlobalDef.pm ${CURDIR}/lib/perl/xCAT/ cp -f ${CURDIR}/../perl-xCAT/xCAT/ServiceNodeUtils.pm ${CURDIR}/lib/perl/xCAT/ diff --git a/build-utils/lib/XCAT/BuildUtils.pm b/build-utils/lib/XCAT/BuildUtils.pm index 86bedd846..e0deac209 100644 --- a/build-utils/lib/XCAT/BuildUtils.pm +++ b/build-utils/lib/XCAT/BuildUtils.pm @@ -141,6 +141,7 @@ sub usage { } use constant XCAT_PROBE_HELPERS => qw( + CommandUtils.pm GlobalDef.pm NetworkUtils.pm ServiceNodeUtils.pm diff --git a/buildrpms.pl b/buildrpms.pl index 70c1c3e8b..1c8b86990 100755 --- a/buildrpms.pl +++ b/buildrpms.pl @@ -65,6 +65,7 @@ system('mkdir', '-p', map { "$ENV{HOME}/rpmbuild/$_" } qw(SOURCES SPECS BUILD BU my $VERSION = read_line("Version") // die "Cannot read Version\n"; my $PWD = Cwd::cwd(); my @XCAT_PROBE_HELPERS = qw( + CommandUtils.pm GlobalDef.pm NetworkUtils.pm ServiceNodeUtils.pm diff --git a/perl-xCAT/xCAT/CommandUtils.pm b/perl-xCAT/xCAT/CommandUtils.pm new file mode 100644 index 000000000..91229a377 --- /dev/null +++ b/perl-xCAT/xCAT/CommandUtils.pm @@ -0,0 +1,54 @@ +package xCAT::CommandUtils; + +use strict; +use warnings; + +our @SYSTEM_FALLBACK_DIRS = qw( + /usr/sbin + /usr/bin + /sbin + /bin +); + +=head1 NAME + +xCAT::CommandUtils - dependency-light command lookup helpers + +=head1 FUNCTIONS + +=head2 find_executable + +Find an executable by searching PATH in order, followed by the standard system +directories. Pass C $value> to search that value instead of the +process PATH. Like the callers this function replaces, empty entries and an +entry named C<0> are ignored. Pass C []> to disable the +standard fallbacks, or supply an array reference to replace them. The matching +candidate path is returned, or undef when none is found. + +=cut + +sub find_executable { + my ( $command, %args ) = @_; + + return unless defined($command) && length($command); + + my $path = exists( $args{path} ) ? $args{path} : $ENV{PATH}; + foreach my $dir ( split /:/, $path || '' ) { + next unless $dir; + my $candidate = "$dir/$command"; + return $candidate if -x $candidate; + } + + my $fallback_dirs = exists( $args{fallback_dirs} ) + ? $args{fallback_dirs} + : \@SYSTEM_FALLBACK_DIRS; + foreach my $dir ( @{ $fallback_dirs || [] } ) { + next unless defined($dir) && length($dir); + my $candidate = "$dir/$command"; + return $candidate if -x $candidate; + } + + return; +} + +1; diff --git a/perl-xCAT/xCAT/DHCP/Backend.pm b/perl-xCAT/xCAT/DHCP/Backend.pm index 7ba20339b..95db9e15c 100644 --- a/perl-xCAT/xCAT/DHCP/Backend.pm +++ b/perl-xCAT/xCAT/DHCP/Backend.pm @@ -3,6 +3,7 @@ package xCAT::DHCP::Backend; use strict; use warnings; +use xCAT::CommandUtils; use xCAT::StringUtils qw(trim); my %valid_backend = map { $_ => 1 } qw(auto isc kea); @@ -142,18 +143,7 @@ sub _osver { sub _command_exists { my ($command) = @_; - - foreach my $dir ( split /:/, $ENV{PATH} || '' ) { - next unless $dir; - my $path = "$dir/$command"; - return 1 if -x $path; - } - - foreach my $path ( "/usr/sbin/$command", "/usr/bin/$command", "/sbin/$command", "/bin/$command" ) { - return 1 if -x $path; - } - - return 0; + return xCAT::CommandUtils::find_executable($command) ? 1 : 0; } 1; diff --git a/perl-xCAT/xCAT/DHCP/Backend/Kea.pm b/perl-xCAT/xCAT/DHCP/Backend/Kea.pm index d4a54ba9d..1cf064669 100644 --- a/perl-xCAT/xCAT/DHCP/Backend/Kea.pm +++ b/perl-xCAT/xCAT/DHCP/Backend/Kea.pm @@ -8,6 +8,7 @@ use File::Basename; use File::Path qw/make_path/; use Math::BigInt; use Text::ParseWords qw/shellwords/; +use xCAT::CommandUtils; use xCAT::DHCP::Range; use xCAT::NetworkUtils; @@ -1206,18 +1207,7 @@ sub _expand_kea_build_path { sub _command_path { my ($command) = @_; - - foreach my $dir ( split /:/, $ENV{PATH} || '' ) { - next unless $dir; - my $path = "$dir/$command"; - return $path if -x $path; - } - - foreach my $path ( "/usr/sbin/$command", "/usr/bin/$command", "/sbin/$command", "/bin/$command" ) { - return $path if -x $path; - } - - return; + return xCAT::CommandUtils::find_executable($command); } sub _shell_quote { diff --git a/xCAT-probe/lib/perl/probe_utils.pm b/xCAT-probe/lib/perl/probe_utils.pm index 7e32742d8..c91e76f5b 100644 --- a/xCAT-probe/lib/perl/probe_utils.pm +++ b/xCAT-probe/lib/perl/probe_utils.pm @@ -8,6 +8,7 @@ use File::Copy; use Time::Local; use Socket; use List::Util qw/sum/; +use xCAT::CommandUtils; #----------------------------------------- @@ -175,11 +176,7 @@ sub _netplan_get { sub _command_available { my $cmd = shift; - for my $dir (split /:/, $ENV{PATH} || '') { - next unless $dir; - return 1 if -x "$dir/$cmd"; - } - return 0; + return xCAT::CommandUtils::find_executable( $cmd, fallback_dirs => [] ) ? 1 : 0; } sub _capture_command { diff --git a/xCAT-server/lib/xcat/plugins/dhcp.pm b/xCAT-server/lib/xcat/plugins/dhcp.pm index 0c7babdf1..e6ddc1eba 100644 --- a/xCAT-server/lib/xcat/plugins/dhcp.pm +++ b/xCAT-server/lib/xcat/plugins/dhcp.pm @@ -24,6 +24,7 @@ use Getopt::Long; Getopt::Long::Configure("bundling"); Getopt::Long::Configure("pass_through"); use Socket; +use xCAT::CommandUtils; my $candoipv6 = eval { require Socket6; 1; @@ -3185,18 +3186,7 @@ sub local_ipv4_routes sub kea_command_path { my ($command) = @_; - - foreach my $dir (split /:/, $ENV{PATH} || '') { - next unless $dir; - my $path = "$dir/$command"; - return $path if -x $path; - } - - foreach my $path ( "/usr/sbin/$command", "/usr/bin/$command", "/sbin/$command", "/bin/$command" ) { - return $path if -x $path; - } - - return; + return xCAT::CommandUtils::find_executable($command); } sub kea_subnet4_intent diff --git a/xCAT-test/autotest/testcase/probe/xcatproble_list b/xCAT-test/autotest/testcase/probe/xcatproble_list index e5471aae9..faf9eec1e 100644 --- a/xCAT-test/autotest/testcase/probe/xcatproble_list +++ b/xCAT-test/autotest/testcase/probe/xcatproble_list @@ -5,7 +5,7 @@ cmd:mkdir -p /tmp/xcatprobe_l cmd:xcatprobe -l check:rc==0 check:output=~Supported sub commands are: -cmd:for module in GlobalDef.pm NetworkUtils.pm ServiceNodeUtils.pm; do test -r "/opt/xcat/probe/lib/perl/xCAT/$module" || exit 1; done +cmd:for module in CommandUtils.pm GlobalDef.pm NetworkUtils.pm ServiceNodeUtils.pm; do test -r "/opt/xcat/probe/lib/perl/xCAT/$module" || exit 1; done check:rc==0 cmd:xcatprobe -l|grep -v "Supported sub commands are" |awk '/^[[:graph:]]/ {print $1}'|sort > /tmp/xcatprobe_l/subcmd_from_xcatprobe_l cmd:ls -l /opt/xcat/probe/subcmds/ |awk '/^-/ {print $9}'|sort > /tmp/xcatprobe_l/subcmd_under_subcmds_dir diff --git a/xCAT-test/integration/dhcp_kea_config_validation.t b/xCAT-test/integration/dhcp_kea_config_validation.t index 7c1408394..5afecaedc 100644 --- a/xCAT-test/integration/dhcp_kea_config_validation.t +++ b/xCAT-test/integration/dhcp_kea_config_validation.t @@ -8,9 +8,10 @@ use File::Temp qw/tempfile/; use JSON (); use Test::More; +use xCAT::CommandUtils; use xCAT::DHCP::Backend::Kea; -my $kea_dhcp4 = command_path('kea-dhcp4'); +my $kea_dhcp4 = xCAT::CommandUtils::find_executable('kea-dhcp4'); plan skip_all => 'kea-dhcp4 is not installed' unless $kea_dhcp4; my $validation_dir = validation_temp_dir($kea_dhcp4); @@ -106,7 +107,7 @@ ok( !$result->{error}, 'generated Kea DHCPv4 config validates with kea-dhcp4 -t' unlink $path; SKIP: { - skip 'kea-dhcp6 is not installed', 1 unless command_path('kea-dhcp6'); + skip 'kea-dhcp6 is not installed', 1 unless xCAT::CommandUtils::find_executable('kea-dhcp6'); my $dhcp6_json = $backend->render_dhcp6_config( { interfaces => ['*'], @@ -150,7 +151,7 @@ SKIP: { } SKIP: { - skip 'kea-dhcp-ddns is not installed', 1 unless command_path('kea-dhcp-ddns'); + skip 'kea-dhcp-ddns is not installed', 1 unless xCAT::CommandUtils::find_executable('kea-dhcp-ddns'); my $ddns_json = $backend->render_ddns_config( { 'tsig-keys' => [ @@ -180,7 +181,7 @@ SKIP: { } SKIP: { - skip 'kea-ctrl-agent is not installed', 1 unless command_path('kea-ctrl-agent'); + skip 'kea-ctrl-agent is not installed', 1 unless xCAT::CommandUtils::find_executable('kea-ctrl-agent'); my $ctrl_agent_json = $backend->render_ctrl_agent_config( { dhcp6 => 1, @@ -195,21 +196,6 @@ SKIP: { } done_testing(); -sub command_path { - my ($command) = @_; - - foreach my $dir ( split /:/, $ENV{PATH} || '' ) { - next unless $dir; - return "$dir/$command" if -x "$dir/$command"; - } - - foreach my $path ( "/usr/sbin/$command", "/usr/bin/$command", "/sbin/$command", "/bin/$command" ) { - return $path if -x $path; - } - - return; -} - sub validation_temp_dir { my ($kea_dhcp4) = @_; diff --git a/xCAT-test/integration/dhcp_kea_control_agent_smoke.t b/xCAT-test/integration/dhcp_kea_control_agent_smoke.t index 5f9473349..df9726940 100644 --- a/xCAT-test/integration/dhcp_kea_control_agent_smoke.t +++ b/xCAT-test/integration/dhcp_kea_control_agent_smoke.t @@ -11,14 +11,15 @@ use POSIX qw/WNOHANG _exit setgid setuid/; use Test::More; use Time::HiRes qw/sleep time/; +use xCAT::CommandUtils; use xCAT::DHCP::Backend::Kea; plan skip_all => 'set XCAT_KEA_LIVE_SMOKE=1 to run live Kea daemon smoke test' unless $ENV{XCAT_KEA_LIVE_SMOKE}; plan skip_all => 'live Kea daemon smoke test must run as root' unless $> == 0; -my $kea_dhcp4 = command_path('kea-dhcp4'); -my $kea_ctrl = command_path('kea-ctrl-agent'); +my $kea_dhcp4 = xCAT::CommandUtils::find_executable('kea-dhcp4'); +my $kea_ctrl = xCAT::CommandUtils::find_executable('kea-ctrl-agent'); plan skip_all => 'kea-dhcp4 and kea-ctrl-agent are required' unless $kea_dhcp4 && $kea_ctrl; @@ -192,21 +193,6 @@ SKIP: { stop_daemons(\%children); done_testing(); -sub command_path { - my ($command) = @_; - - foreach my $dir ( split /:/, $ENV{PATH} || '' ) { - next unless $dir; - return "$dir/$command" if -x "$dir/$command"; - } - - foreach my $path ( "/usr/sbin/$command", "/usr/bin/$command", "/sbin/$command", "/bin/$command" ) { - return $path if -x $path; - } - - return; -} - sub start_daemon { my ( $account, $command, $log, @args ) = @_; my $pid = fork(); diff --git a/xCAT-test/unit/command_utils.t b/xCAT-test/unit/command_utils.t new file mode 100644 index 000000000..7eb4da02c --- /dev/null +++ b/xCAT-test/unit/command_utils.t @@ -0,0 +1,210 @@ +use strict; +use warnings; + +use FindBin; +use lib "$FindBin::Bin/../lib"; +use lib "$FindBin::Bin/../../perl-xCAT"; + +use Cwd qw/getcwd/; +use File::Path qw/make_path/; +use File::Slurper qw/write_text/; +use File::Temp qw/tempdir/; +use Test::More; + +use xCAT::CommandUtils; + +is_deeply( + \@xCAT::CommandUtils::SYSTEM_FALLBACK_DIRS, + [qw(/usr/sbin /usr/bin /sbin /bin)], + 'the built-in system fallback order matches the replaced callers' +); + +my $root = tempdir(CLEANUP => 1); +my $first_dir = "$root/first"; +my $second_dir = "$root/second"; +my $fallback_dir = "$root/fallback"; +make_path( $first_dir, $second_dir, $fallback_dir, "$root/relative" ); + +sub write_executable { + my ($path) = @_; + write_text( $path, "#!/bin/sh\nexit 0\n" ); + chmod 0755, $path or die "Unable to make $path executable: $!"; + return $path; +} + +my $first_tool = write_executable("$first_dir/xcat-command-utils-tool"); +my $second_tool = write_executable("$second_dir/xcat-command-utils-tool"); + +is( + xCAT::CommandUtils::find_executable( + 'xcat-command-utils-tool', + path => "$first_dir:$second_dir", + fallback_dirs => [], + ), + $first_tool, + 'PATH entries are searched in order' +); + +chmod 0644, $first_tool or die "Unable to remove execute permission from $first_tool: $!"; +is( + xCAT::CommandUtils::find_executable( + 'xcat-command-utils-tool', + path => "$first_dir:$second_dir", + fallback_dirs => [], + ), + $second_tool, + 'non-executable candidates are skipped' +); + +{ + local $ENV{PATH} = $second_dir; + is( + xCAT::CommandUtils::find_executable('xcat-command-utils-tool'), + $second_tool, + 'the process PATH is used by default' + ); + is( + xCAT::CommandUtils::find_executable( + 'xcat-command-utils-tool', + path => $first_dir, + fallback_dirs => [], + ), + undef, + 'an explicit path overrides the process PATH' + ); +} + +my $fallback_tool = write_executable("$fallback_dir/xcat-command-utils-fallback"); +is( + xCAT::CommandUtils::find_executable( + 'xcat-command-utils-fallback', + path => '', + fallback_dirs => [ '', $fallback_dir ], + ), + $fallback_tool, + 'custom fallback directories are searched after PATH and ignore empty entries' +); +is( + xCAT::CommandUtils::find_executable( + 'xcat-command-utils-fallback', + path => '', + fallback_dirs => [], + ), + undef, + 'fallback lookup can be disabled' +); +is( + xCAT::CommandUtils::find_executable( + 'bin', + path => '', + fallback_dirs => [''], + ), + undef, + 'empty fallback entries are ignored instead of matching executable root directories' +); +is( + xCAT::CommandUtils::find_executable( + 'xcat-command-utils-tool', + path => '', + fallback_dirs => [$first_dir], + ), + undef, + 'non-executable fallback candidates are skipped' +); + +my $fallback_order_first = write_executable("$first_dir/xcat-command-utils-fallback-order"); +write_executable("$second_dir/xcat-command-utils-fallback-order"); +is( + xCAT::CommandUtils::find_executable( + 'xcat-command-utils-fallback-order', + path => '', + fallback_dirs => [ $first_dir, $second_dir ], + ), + $fallback_order_first, + 'custom fallback directories are searched in order' +); + +my $path_collision = write_executable("$second_dir/xcat-command-utils-collision"); +write_executable("$fallback_dir/xcat-command-utils-collision"); +is( + xCAT::CommandUtils::find_executable( + 'xcat-command-utils-collision', + path => $second_dir, + fallback_dirs => [$fallback_dir], + ), + $path_collision, + 'PATH matches take precedence over fallback matches' +); + +my $system_shell = xCAT::CommandUtils::find_executable( 'sh', path => '' ); +my ($expected_system_shell) = grep { -x "$_/sh" } qw(/usr/sbin /usr/bin /sbin /bin); +is( + $system_shell, + defined($expected_system_shell) ? "$expected_system_shell/sh" : undef, + 'standard system directories are searched by default' +); + +my $original_dir = getcwd(); +chdir($root) or die "Unable to enter $root: $!"; +is( + xCAT::CommandUtils::find_executable( + 'bin', + path => ":$second_dir", + fallback_dirs => [], + ), + undef, + 'empty PATH entries are ignored instead of matching executable root directories' +); + +write_executable("$root/relative/xcat-command-utils-relative"); +is( + xCAT::CommandUtils::find_executable( + 'xcat-command-utils-relative', + path => 'relative', + fallback_dirs => [], + ), + 'relative/xcat-command-utils-relative', + 'relative PATH entries preserve the existing candidate path shape' +); + +make_path("$root/0"); +write_executable("$root/0/xcat-command-utils-zero-entry"); +is( + xCAT::CommandUtils::find_executable( + 'xcat-command-utils-zero-entry', + path => "0:$second_dir", + fallback_dirs => [], + ), + undef, + 'a PATH component named zero retains the existing falsy-entry behavior' +); +chdir($original_dir) or die "Unable to restore $original_dir: $!"; + +my $marker = "$root/shell-was-invoked"; +my $literal_name = 'xcat-command-utils;touch shell-was-invoked'; +my $literal_tool = write_executable("$second_dir/$literal_name"); +chdir($root) or die "Unable to enter $root for shell-safety lookup: $!"; +is( + xCAT::CommandUtils::find_executable( + $literal_name, + path => $second_dir, + fallback_dirs => [], + ), + $literal_tool, + 'command names are treated as filesystem paths without shell interpretation' +); +ok( !-e $marker, 'executable lookup never invokes a shell' ); +chdir($original_dir) or die "Unable to restore $original_dir: $!"; + +is( + xCAT::CommandUtils::find_executable( undef, path => $second_dir ), + undef, + 'an undefined command is not searched' +); +is( + xCAT::CommandUtils::find_executable( '', path => $second_dir ), + undef, + 'an empty command is not searched' +); + +done_testing(); diff --git a/xCAT-test/unit/dhcp_backend_selection.t b/xCAT-test/unit/dhcp_backend_selection.t index f6450cf21..179be060d 100644 --- a/xCAT-test/unit/dhcp_backend_selection.t +++ b/xCAT-test/unit/dhcp_backend_selection.t @@ -307,4 +307,12 @@ is( 'forced Kea succeeds when available' ); +{ + local $ENV{PATH} = ''; + ok( + xCAT::DHCP::Backend::_command_exists('sh'), + 'backend availability retains the standard system-directory fallback' + ); +} + done_testing(); diff --git a/xCAT-test/unit/dhcp_kea_plugin_intent.t b/xCAT-test/unit/dhcp_kea_plugin_intent.t index 839de3bec..4e338ae6d 100644 --- a/xCAT-test/unit/dhcp_kea_plugin_intent.t +++ b/xCAT-test/unit/dhcp_kea_plugin_intent.t @@ -4,12 +4,14 @@ use warnings; no warnings 'once'; use FindBin; +use lib "$FindBin::Bin/../lib"; use lib "$FindBin::Bin/../../perl-xCAT"; use lib "$FindBin::Bin/../../xCAT-server/lib/perl"; use File::Temp qw(tempdir); use Socket (); use Test::More; +use XCAT::Test::File qw(repo_path); BEGIN { package xCAT::Table; @@ -81,12 +83,8 @@ require xCAT::Utils; *xCAT::Utils::runcmd = sub { return; }; } -my $source_dhcp_plugin = "$FindBin::Bin/../../xCAT-server/lib/xcat/plugins/dhcp.pm"; -if ( -f $source_dhcp_plugin ) { - require $source_dhcp_plugin; -} else { - require xCAT_plugin::dhcp; -} +my $source_dhcp_plugin = repo_path('xCAT-server/lib/xcat/plugins/dhcp.pm'); +require $source_dhcp_plugin; require xCAT::DHCP::Backend::Kea; { @@ -162,6 +160,15 @@ foreach my $case (@sysconfig_policy_cases) { close($ip_fh); chmod 0755, $fake_ip; + { + local $ENV{PATH} = $tmpdir; + is( + xCAT_plugin::dhcp::kea_command_path('ip'), + $fake_ip, + 'DHCP route command lookup retains the first executable PATH match' + ); + } + no warnings 'redefine'; local *xCAT_plugin::dhcp::kea_command_path = sub { my ($command) = @_; diff --git a/xCAT-test/unit/dhcp_kea_renderer.t b/xCAT-test/unit/dhcp_kea_renderer.t index e9b31c708..295cd329d 100644 --- a/xCAT-test/unit/dhcp_kea_renderer.t +++ b/xCAT-test/unit/dhcp_kea_renderer.t @@ -580,6 +580,15 @@ FAKE_KEA close($fake_kea_fh) or die "Unable to close fake Kea command: $!"; chmod 0755, $fake_kea_dhcp4 or die "Unable to make fake Kea command executable: $!"; +{ + local $ENV{PATH} = $unit_dir; + is( + xCAT::DHCP::Backend::Kea::_command_path('kea-dhcp4-build-report'), + $fake_kea_dhcp4, + 'Kea command lookup retains the first executable PATH match' + ); +} + my $command_socket_backend = xCAT::DHCP::Backend::Kea->new(kea_dhcp4_command => $fake_kea_dhcp4); is( $command_socket_backend->control_socket_path('kea4-ctrl-socket'), '/xcat-test-command-run/kea/kea4-ctrl-socket', 'socket path comes from the Kea build-report command' ); diff --git a/xCAT-test/unit/probe_utils_dhcp_reply.t b/xCAT-test/unit/probe_utils_dhcp_reply.t index 4d432a0d4..69f55120b 100644 --- a/xCAT-test/unit/probe_utils_dhcp_reply.t +++ b/xCAT-test/unit/probe_utils_dhcp_reply.t @@ -3,6 +3,7 @@ use strict; use warnings; use FindBin; +use lib "$FindBin::Bin/../../perl-xCAT"; use lib "$FindBin::Bin/../../xCAT-probe/lib/perl"; use Test::More; diff --git a/xCAT-test/unit/probe_utils_netplan.t b/xCAT-test/unit/probe_utils_netplan.t index c31a5b733..46521e830 100644 --- a/xCAT-test/unit/probe_utils_netplan.t +++ b/xCAT-test/unit/probe_utils_netplan.t @@ -3,6 +3,7 @@ use strict; use warnings; use FindBin; +use lib "$FindBin::Bin/../../perl-xCAT"; use lib "$FindBin::Bin/../../xCAT-probe/lib/perl"; use File::Slurper qw(write_text); diff --git a/xCAT-test/unit/probe_utils_netplan_get.t b/xCAT-test/unit/probe_utils_netplan_get.t index 8a7068897..a20f57c25 100644 --- a/xCAT-test/unit/probe_utils_netplan_get.t +++ b/xCAT-test/unit/probe_utils_netplan_get.t @@ -3,6 +3,7 @@ use strict; use warnings; use FindBin; +use lib "$FindBin::Bin/../../perl-xCAT"; use lib "$FindBin::Bin/../../xCAT-probe/lib/perl"; use File::Temp qw(tempdir); diff --git a/xCAT-test/unit/probe_utils_tcp_listener.t b/xCAT-test/unit/probe_utils_tcp_listener.t index 07d14913e..6942653a5 100644 --- a/xCAT-test/unit/probe_utils_tcp_listener.t +++ b/xCAT-test/unit/probe_utils_tcp_listener.t @@ -3,6 +3,7 @@ use strict; use warnings; use FindBin; +use lib "$FindBin::Bin/../../perl-xCAT"; use lib "$FindBin::Bin/../../xCAT-probe/lib/perl"; use Test::More; @@ -49,6 +50,14 @@ ok(probe_utils::_tcp_listener_output_has_port($netstat_output, 80, qr/httpd|apac ok(!probe_utils::_tcp_listener_output_has_port($netstat_output, 0), 'invalid port is rejected'); ok(!probe_utils::_tcp_listener_output_has_port($netstat_output, 'http'), 'non-numeric port is rejected'); +{ + local $ENV{PATH} = ''; + ok( + !probe_utils::_command_available('sh'), + 'probe command discovery retains PATH-only lookup without system fallbacks' + ); +} + { no warnings 'redefine'; my @commands; diff --git a/xCAT-test/unit/xcat_probe_package_payload.t b/xCAT-test/unit/xcat_probe_package_payload.t index 0db35af2b..26659bcdf 100644 --- a/xCAT-test/unit/xcat_probe_package_payload.t +++ b/xCAT-test/unit/xcat_probe_package_payload.t @@ -9,11 +9,14 @@ use File::Spec; use File::Temp qw(tempdir); use FindBin; use lib "$FindBin::Bin/../lib"; +use lib "$FindBin::Bin/../../build-utils/lib"; use Test::More; +use XCAT::BuildUtils qw(XCAT_PROBE_HELPERS); use XCAT::Test::File qw(repo_path slurp_repo_file); my @helpers = qw( + CommandUtils.pm GlobalDef.pm NetworkUtils.pm ServiceNodeUtils.pm @@ -26,6 +29,9 @@ my @affected_subcommands = qw( ); my $builder = slurp_repo_file('buildrpms.pl'); +my $debian_builder = slurp_repo_file('build-ubunturepo'); +my $installed_probe_test = + slurp_repo_file('xCAT-test/autotest/testcase/probe/xcatproble_list'); my $rpm_spec = slurp_repo_file('xCAT-probe/xCAT-probe.spec'); my $debian_control = slurp_repo_file('xCAT-probe/debian/control'); like($builder, qr/sub prepare_xcat_probe_source_tar\b/, 'RPM builder has dedicated xCAT-probe source preparation'); @@ -65,6 +71,20 @@ for my $helper (@helpers) { my $source = repo_path(File::Spec->catfile('perl-xCAT', 'xCAT', $helper)); ok(-f $source, "$helper source exists"); like($builder, qr/^\s*\Q$helper\E\s*$/m, "RPM builder stages $helper"); + ok( + scalar(grep { $_ eq $helper } XCAT_PROBE_HELPERS), + "the shared builder helper list carries $helper" + ); + like( + $debian_builder, + qr{cp -f [^\n]*/perl-xCAT/xCAT/\Q$helper\E\s+[^\n]*/lib/perl/xCAT/}, + "Debian builder stages $helper" + ); + like( + $installed_probe_test, + qr/cmd:for module in [^;]*\b\Q$helper\E\b[^;]*; do test -r/, + "installed probe payload checks $helper" + ); } my $tmpdir = tempdir(CLEANUP => 1);