From 1882d2d0fe4312b2185aae3206ade5c9a543ecc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Ferr=C3=A3o?= <2031761+viniciusferrao@users.noreply.github.com> Date: Sat, 10 Oct 2026 21:12:08 -0300 Subject: [PATCH 1/3] test(xcat): resolve trim callers from the checkout --- xCAT-test/unit/blade_findme_chassis_filter.t | 6 +++--- xCAT-test/unit/credentials_service_node.t | 8 ++++---- xCAT-test/unit/credentials_system_password.t | 9 ++++----- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/xCAT-test/unit/blade_findme_chassis_filter.t b/xCAT-test/unit/blade_findme_chassis_filter.t index 444017572..8ec755f9a 100644 --- a/xCAT-test/unit/blade_findme_chassis_filter.t +++ b/xCAT-test/unit/blade_findme_chassis_filter.t @@ -3,10 +3,10 @@ use strict; use warnings; use FindBin; -use File::Spec; use Test::More; -use lib File::Spec->catdir( $FindBin::Bin, '..', '..', - 'xCAT-server', 'lib', 'perl' ); +use lib "$FindBin::Bin/../lib"; +use XCAT::Test::File qw(repo_path); +use lib repo_path('perl-xCAT'), repo_path('xCAT-server/lib/perl'); use xCAT::BladeUtils; sub blades { diff --git a/xCAT-test/unit/credentials_service_node.t b/xCAT-test/unit/credentials_service_node.t index b1cfed285..8c2bb408b 100644 --- a/xCAT-test/unit/credentials_service_node.t +++ b/xCAT-test/unit/credentials_service_node.t @@ -7,6 +7,9 @@ use File::Spec; use File::Temp qw(tempdir); use FindBin; use Test::More; +use lib "$FindBin::Bin/../lib"; +use XCAT::Test::File qw(repo_path); +use lib repo_path('perl-xCAT'); BEGIN { package xCAT::Table; @@ -97,10 +100,7 @@ BEGIN { $INC{'HTTP/Request/Common.pm'} = 1; } -my $repo_root = File::Spec->catdir( $FindBin::Bin, '..', '..' ); -my $plugin = File::Spec->catfile( - $repo_root, qw(xCAT-server lib xcat plugins credentials.pm) -); +my $plugin = repo_path('xCAT-server/lib/xcat/plugins/credentials.pm'); require $plugin; sub reset_client { diff --git a/xCAT-test/unit/credentials_system_password.t b/xCAT-test/unit/credentials_system_password.t index 02eb3710f..f0d669c47 100644 --- a/xCAT-test/unit/credentials_system_password.t +++ b/xCAT-test/unit/credentials_system_password.t @@ -3,9 +3,11 @@ use strict; use warnings; -use File::Spec; use FindBin; use Test::More; +use lib "$FindBin::Bin/../lib"; +use XCAT::Test::File qw(repo_path); +use lib repo_path('perl-xCAT'); BEGIN { package xCAT::Table; @@ -96,10 +98,7 @@ BEGIN { $INC{'HTTP/Request/Common.pm'} = 1; } -my $repo_root = File::Spec->catdir( $FindBin::Bin, '..', '..' ); -my $plugin = File::Spec->catfile( - $repo_root, qw(xCAT-server lib xcat plugins credentials.pm) -); +my $plugin = repo_path('xCAT-server/lib/xcat/plugins/credentials.pm'); require $plugin; # The node callback on port 300 is the only part that needs a live node. From 4879eef80b0e9edf261e132df9a562b87d690ff1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Ferr=C3=A3o?= <2031761+viniciusferrao@users.noreply.github.com> Date: Sat, 10 Oct 2026 21:13:41 -0300 Subject: [PATCH 2/3] refactor(xcat): reuse whitespace trimming in blade and credential paths --- xCAT-server/lib/perl/xCAT/BladeUtils.pm | 4 +++- xCAT-server/lib/xcat/plugins/credentials.pm | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/xCAT-server/lib/perl/xCAT/BladeUtils.pm b/xCAT-server/lib/perl/xCAT/BladeUtils.pm index fd2fef6f2..66588b216 100644 --- a/xCAT-server/lib/perl/xCAT/BladeUtils.pm +++ b/xCAT-server/lib/perl/xCAT/BladeUtils.pm @@ -3,6 +3,8 @@ package xCAT::BladeUtils; use strict; use warnings; +use xCAT::StringUtils qw(trim); + sub blade_nodes_from_mp { my @entries = @_; my %hwtype; @@ -12,7 +14,7 @@ sub blade_nodes_from_mp { next unless ref $entry eq 'HASH' and defined $entry->{node}; $hwtype{ $entry->{node} } = defined $entry->{nodetype} ? lc( $entry->{nodetype} ) : q{}; - $hwtype{ $entry->{node} } =~ s/^\s+|\s+$//gx; + $hwtype{ $entry->{node} } = trim($hwtype{ $entry->{node} }); $ownmpa{ $entry->{node} } = $entry->{mpa} if defined $entry->{mpa}; } diff --git a/xCAT-server/lib/xcat/plugins/credentials.pm b/xCAT-server/lib/xcat/plugins/credentials.pm index 785dc843e..9a69047dd 100644 --- a/xCAT-server/lib/xcat/plugins/credentials.pm +++ b/xCAT-server/lib/xcat/plugins/credentials.pm @@ -38,6 +38,7 @@ use xCAT::Utils; use xCAT::NetworkUtils; use xCAT::PasswordUtils; use xCAT::TableUtils; +use xCAT::StringUtils qw(trim); use xCAT::MsgUtils; use Getopt::Long; @@ -410,7 +411,7 @@ sub _delegated_signer_allowed { sub _endpoint_identities { my $endpoint = shift; return unless defined($endpoint); - $endpoint =~ s/^\s+|\s+$//g; + $endpoint = trim($endpoint); return unless length($endpoint); my %identities; From 0349bb64d663dd2043106372356171801d04b355 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Ferr=C3=A3o?= <2031761+viniciusferrao@users.noreply.github.com> Date: Sat, 10 Oct 2026 21:15:29 -0300 Subject: [PATCH 3/3] test(xcat): cover whitespace in blade and credential identities --- xCAT-test/unit/blade_findme_chassis_filter.t | 31 +++++++++++++ xCAT-test/unit/credentials_service_node.t | 46 ++++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/xCAT-test/unit/blade_findme_chassis_filter.t b/xCAT-test/unit/blade_findme_chassis_filter.t index 8ec755f9a..5d643f830 100644 --- a/xCAT-test/unit/blade_findme_chassis_filter.t +++ b/xCAT-test/unit/blade_findme_chassis_filter.t @@ -83,4 +83,35 @@ is_deeply( blades(), [], 'an empty table asks nothing' ); is_deeply( blades( {}, { node => 'x220b', nodetype => 'blade' } ), ['x220b'], 'a row without a node name is skipped' ); +foreach my $case ( + [ 'mixed case and line endings', "\tBlAdE\r\n", ['blade-one'] ], + [ 'Unicode whitespace', "\x{2003}blade\x{2003}", ['blade-one'] ], + [ 'undefined type', undef, ['blade-one'] ], + [ 'empty type', '', ['blade-one'] ], + [ 'blank type', " \t\r\n", ['blade-one'] ], + [ 'internal whitespace', 'bl ade', [] ], + [ 'other hardware type', ' pbmc ', [] ], + [ 'defined false type', '0', [] ], +) { + my ($label, $type, $expected) = @{$case}; + my @entries = ( + { node => 'chassis', nodetype => " \tMm\r\n" }, + { node => 'blade-one', mpa => 'chassis', nodetype => $type }, + ); + my @original = map { { %{$_} } } @entries; + is_deeply( [ xCAT::BladeUtils::blade_nodes_from_mp(@entries) ], + $expected, "$label preserves blade selection" ); + is_deeply( \@entries, \@original, "$label leaves table rows unchanged" ); +} + +is_deeply( + [ xCAT::BladeUtils::blade_nodes_from_mp( + { node => 'blade-b', nodetype => "\tblade\n" }, + { node => 'blade-a', nodetype => ' BLADE ' }, + { node => 'blade-b', nodetype => "\tblade\n" }, + ) ], + [ 'blade-b', 'blade-a', 'blade-b' ], + 'selection preserves input order and duplicate rows' +); + done_testing(); diff --git a/xCAT-test/unit/credentials_service_node.t b/xCAT-test/unit/credentials_service_node.t index 8c2bb408b..ea6d9d0ce 100644 --- a/xCAT-test/unit/credentials_service_node.t +++ b/xCAT-test/unit/credentials_service_node.t @@ -44,9 +44,11 @@ BEGIN { package xCAT::NetworkUtils; our %addresses; + our @lookups; sub import { } sub getipaddr { my ($class, $endpoint) = @_; + push @lookups, $endpoint; return @{ $addresses{$endpoint} || [] }; } $INC{'xCAT/NetworkUtils.pm'} = 1; @@ -119,6 +121,50 @@ is( $commands->{getcredentials}, 'credentials', is( $commands->{signx509cert}, 'credentials', 'credentials plugin handles delegated signing' ); +{ + local %xCAT::NetworkUtils::addresses = ( + 'Service-B.Example.Test.' => ['192.0.2.22'], + ); + foreach my $case ( + [ 'undefined endpoint', undef, undef, [] ], + [ 'empty endpoint', '', undef, [] ], + [ 'blank endpoint', " \t\r\n", undef, [] ], + [ 'defined false endpoint', '0', '0', ['0'] ], + [ 'padded endpoint', " \tService-B.Example.Test.\r\n", + 'Service-B.Example.Test.', ['192.0.2.22', 'service-b.example.test'] ], + [ 'Unicode padding', "\x{2003}Service-B.Example.Test.\x{2003}", + 'Service-B.Example.Test.', ['192.0.2.22', 'service-b.example.test'] ], + [ 'IPv4-mapped endpoint', " \t::ffff:192.0.2.22\n", + '::ffff:192.0.2.22', ['192.0.2.22'] ], + [ 'internal whitespace', ' service b ', 'service b', ['service b'] ], + ) { + my ($label, $input, $lookup, $expected) = @{$case}; + my $original = $input; + local @xCAT::NetworkUtils::lookups; + my @identities = xCAT_plugin::credentials::_endpoint_identities($input); + is_deeply( [ sort @identities ], $expected, "$label preserves identities" ); + is_deeply( \@xCAT::NetworkUtils::lookups, + defined($lookup) ? [$lookup] : [], "$label preserves DNS input" ); + is( $input, $original, "$label leaves the caller input unchanged" ); + } + + local $xCAT::Table::servicenode = " \tService-B.Example.Test.\r\n"; + foreach my $case ( + [ 'padded assigned peer', " \t192.0.2.22\r\n", 1 ], + [ 'different peer', '192.0.2.23', 0 ], + [ 'empty peer', '', 0 ], + [ 'blank peer', " \t\r\n", 0 ], + [ 'undefined peer', undef, 0 ], + ) { + my ($label, $peer, $expected) = @{$case}; + is( xCAT_plugin::credentials::_delegated_signer_allowed( + { _xcat_authname => ['root'], _xcat_clientip => [$peer] }, + 'compute-01' + ), + $expected, "$label preserves delegated signer authorization" ); + } +} + $xCAT::Table::servicenode = 'service-a, service-b.example.test'; %xCAT::NetworkUtils::addresses = ( '192.0.2.21' => ['192.0.2.21'],