From eb76a336524ad9d55f5e41ab4f7d333f835cab4d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Vin=C3=ADcius=20Ferr=C3=A3o?=
<2031761+viniciusferrao@users.noreply.github.com>
Date: Thu, 8 Oct 2026 16:09:46 -0300
Subject: [PATCH] test(genesis): load production architecture and repository
owners
---
xCAT-test/bats/fixtures/go-xcat-common.sh | 18 +++
xCAT-test/bats/go_xcat_common_repository.bats | 149 ++++++------------
.../bats/go_xcat_genesis_package_names.bats | 19 +--
xCAT-test/unit/destiny_genesis_architecture.t | 53 +++----
.../unit/xcatconfig_genesis_openembedded.t | 36 +++--
5 files changed, 125 insertions(+), 150 deletions(-)
create mode 100644 xCAT-test/bats/fixtures/go-xcat-common.sh
diff --git a/xCAT-test/bats/fixtures/go-xcat-common.sh b/xCAT-test/bats/fixtures/go-xcat-common.sh
new file mode 100644
index 000000000..74e820ef3
--- /dev/null
+++ b/xCAT-test/bats/fixtures/go-xcat-common.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+PATH=""
+source /tmp/go-xcat || exit 70
+TMP_DIR=/tmp/fixture
+GO_XCAT_DEFAULT_BASE_URL=https://repo.example.invalid
+GO_XCAT_DEFAULT_INSTALL_PATH=/tmp/fixture/install
+
+yum() { printf '%s\n' "$*" >> /tmp/fixture/yum.log; }
+download_file()
+{
+ printf '%s\n' "$1" >> /tmp/fixture/download.log
+ [ "$COMMON_PRESENT" = 1 ] || return 1
+ printf '\n' > "$2"
+}
+
+add_xcat_dep_common_repo_yum_or_zypper "$1" "$2" || exit $?
+refresh_xcat_dep_repository_ids
+printf '%s\n' "${GO_XCAT_DEP_REPOSITORY_IDS[*]}" > /tmp/fixture/ids
diff --git a/xCAT-test/bats/go_xcat_common_repository.bats b/xCAT-test/bats/go_xcat_common_repository.bats
index b49f4fce0..0a36d4ea3 100644
--- a/xCAT-test/bats/go_xcat_common_repository.bats
+++ b/xCAT-test/bats/go_xcat_common_repository.bats
@@ -4,119 +4,74 @@ load 'helpers/go_xcat'
setup()
{
- go_xcat_require_source
+ [ "$(uname -s)" = Linux ] || skip 'repository checks require Linux namespaces'
+ GO_XCAT_SOURCE="${XCAT_TEST_GO_XCAT:-$(go_xcat_default_source)}"
+ [ -r "$GO_XCAT_SOURCE" ] || return 1
+ [ -n "$BATS_TEST_TMPDIR" ] || return 1
+ fixture="$BATS_TEST_TMPDIR/repository"
+ mkdir -p "$fixture/etc/yum.repos.d"
+ COMMON_PRESENT=1
}
-run_common_repository_case()
+configure_repository()
{
- local case_dir="$1"
- local common_present="$2"
- shift 2
-
- mkdir -p "$case_dir"
- export ADD_LOG="${case_dir}/add.log"
- export COMMON_PRESENT="$common_present"
- export DOWNLOAD_LOG="${case_dir}/download.log"
- export ID_LOG="${case_dir}/id.log"
- export TEST_TMP="$case_dir"
-
- go_xcat_load_functions \
- add_xcat_dep_common_repo_yum_or_zypper \
- xcat_dep_common_repo_configured \
- refresh_xcat_dep_repository_ids
-
- TMP_DIR="$TEST_TMP"
- GO_XCAT_DEFAULT_BASE_URL=https://repo.example.invalid
- GO_XCAT_DEP_REPOSITORY_IDS=(xcat-dep)
-
- yum() { :; }
-
- download_file()
- {
- printf '%s\n' "$1" >>"$DOWNLOAD_LOG"
- [[ ${COMMON_PRESENT:-0} == 1 ]] || return 1
- : >"$2"
- }
-
- add_repo_by_url_yum_or_zypper()
- {
- printf '%s %s\n' "$1" "$2" >>"$ADD_LOG"
- }
-
- xcat_dep_common_repo_configured()
- {
- [[ -s "$ADD_LOG" ]]
- }
-
- ( add_xcat_dep_common_repo_yum_or_zypper "$@" )
- refresh_xcat_dep_repository_ids
- printf '%s\n' "${GO_XCAT_DEP_REPOSITORY_IDS[*]}" >"$ID_LOG"
+ bwrap --die-with-parent --unshare-net --ro-bind / / --dev /dev --proc /proc \
+ --tmpfs /tmp --ro-bind "$BATS_TEST_DIRNAME/../.." /tmp/source \
+ --ro-bind "$GO_XCAT_SOURCE" /tmp/go-xcat \
+ --bind "$fixture" /tmp/fixture --bind "$fixture/etc" /etc \
+ --setenv COMMON_PRESENT "$COMMON_PRESENT" --chdir /tmp/fixture \
+ bash /tmp/source/xCAT-test/bats/fixtures/go-xcat-common.sh "$@"
}
-run_template_generation()
-{
- local tmp_dir="$1"
- local repo_log="$2"
-
- mkdir -p "$tmp_dir"
- export REPO_LOG="$repo_log"
- export TEST_TMP="$tmp_dir"
-
- go_xcat_load_functions add_repo_by_url_yum_or_zypper
-
- TMP_DIR="$TEST_TMP"
- GO_XCAT_DEFAULT_INSTALL_PATH=/install/xcat
- yum() { :; }
- add_repo_by_file() { cp "$1" "$REPO_LOG"; }
-
- add_repo_by_url_yum_or_zypper \
- https://repo.example.invalid/xcat-dep/common xcat-dep-common optional
-}
-
-@test "an available remote common repository is enabled" {
- local case_dir="${BATS_TEST_TMPDIR}/remote-present"
-
- run run_common_repository_case "$case_dir" 1 "" latest
- [ "$status" -eq 0 ]
- [ "$(read_file_or_empty "${case_dir}/download.log")" = "https://repo.example.invalid/yum/latest/xcat-dep/common/repodata/repomd.xml" ]
- [ "$(read_file_or_empty "${case_dir}/add.log")" = "https://repo.example.invalid/yum/latest/xcat-dep/common xcat-dep-common" ]
- [ "$(read_file_or_empty "${case_dir}/id.log")" = "xcat-dep xcat-dep-common" ]
+@test "an available remote common repository is installed and activated" {
+ run configure_repository '' latest
+ [ "$status" -eq 0 ] || { printf '%s\n' "$output"; return 1; }
+ [ "$(cat "$fixture/download.log")" = 'https://repo.example.invalid/yum/latest/xcat-dep/common/repodata/repomd.xml' ]
+ [ "$(cat "$fixture/ids")" = 'xcat-dep xcat-dep-common' ]
+ repo="$fixture/etc/yum.repos.d/xcat-dep-common.repo"
+ grep -Fxq '[xcat-dep-common]' "$repo"
+ grep -Fxq 'baseurl=https://repo.example.invalid/yum/latest/xcat-dep/common' "$repo"
+ grep -Fxq 'enabled=1' "$repo"
+ grep -Fxq 'skip_if_unavailable=1' "$repo"
+ grep -Fxq 'repo_gpgcheck=1' "$repo"
+ grep -Fxq 'gpgcheck=1' "$repo"
+ grep -Fxq 'gpgkey=https://repo.example.invalid/yum/latest/xcat-dep/common/repodata/repomd.xml.key' "$repo"
+ [ "$(cat "$fixture/yum.log")" = 'clean metadata' ]
}
@test "a release without the remote common repository remains usable" {
- local case_dir="${BATS_TEST_TMPDIR}/remote-missing"
-
- run run_common_repository_case "$case_dir" 0 "" 2.18
+ COMMON_PRESENT=0
+ run configure_repository '' 2.18
[ "$status" -eq 0 ]
- [ "$(read_file_or_empty "${case_dir}/add.log")" = "" ]
- [ "$(read_file_or_empty "${case_dir}/id.log")" = "xcat-dep" ]
+ [ "$(cat "$fixture/ids")" = xcat-dep ]
+ [ ! -e "$fixture/etc/yum.repos.d/xcat-dep-common.repo" ]
+ [ ! -e "$fixture/yum.log" ]
}
@test "a custom repository file does not guess an unrelated common repository" {
- local case_dir="${BATS_TEST_TMPDIR}/repo-file"
-
- run run_common_repository_case "$case_dir" 1 https://repo.example.invalid/custom/xcat-dep.repo latest
+ run configure_repository https://repo.example.invalid/custom/xcat-dep.repo latest
[ "$status" -eq 0 ]
- [ "$(read_file_or_empty "${case_dir}/download.log")" = "" ]
- [ "$(read_file_or_empty "${case_dir}/add.log")" = "" ]
+ [ ! -e "$fixture/download.log" ]
+ [ ! -e "$fixture/etc/yum.repos.d/xcat-dep-common.repo" ]
+ [ "$(cat "$fixture/ids")" = xcat-dep ]
}
-@test "a local common repository is enabled beside the distribution repository" {
- local local_root="${BATS_TEST_TMPDIR}/local-repository"
- local case_dir="${BATS_TEST_TMPDIR}/local-present"
- mkdir -p "${local_root}/common/repodata"
- : >"${local_root}/common/repodata/repomd.xml"
-
- run run_common_repository_case "$case_dir" 0 "$local_root" latest
- [ "$status" -eq 0 ]
- [ "$(read_file_or_empty "${case_dir}/add.log")" = "${local_root}/common xcat-dep-common" ]
+@test "a local common repository is installed beside the distribution repository" {
+ mkdir -p "$fixture/local/common/repodata"
+ printf '\n' > "$fixture/local/common/repodata/repomd.xml"
+ run configure_repository /tmp/fixture/local latest
+ [ "$status" -eq 0 ] || { printf '%s\n' "$output"; return 1; }
+ [ ! -e "$fixture/download.log" ]
+ [ "$(cat "$fixture/ids")" = 'xcat-dep xcat-dep-common' ]
+ grep -Fxq 'baseurl=file:///tmp/fixture/local/common' "$fixture/etc/yum.repos.d/xcat-dep-common.repo"
}
-@test "the optional common repository template tolerates outages and verifies metadata" {
- local template_log="${BATS_TEST_TMPDIR}/generated-common.repo"
-
- run run_template_generation "$BATS_TEST_TMPDIR" "$template_log"
+@test "an existing zypper common repository is retained without a new download" {
+ mkdir -p "$fixture/etc/zypp/repos.d"
+ printf '[xcat-dep-common]\n' > "$fixture/etc/zypp/repos.d/xcat-dep-common.repo"
+ COMMON_PRESENT=0
+ run configure_repository '' latest
[ "$status" -eq 0 ]
- grep -Fxq 'skip_if_unavailable=1' "$template_log"
- grep -Fxq 'repo_gpgcheck=1' "$template_log"
+ [ "$(cat "$fixture/ids")" = 'xcat-dep xcat-dep-common' ]
+ [ "$(cat "$fixture/etc/zypp/repos.d/xcat-dep-common.repo")" = '[xcat-dep-common]' ]
}
diff --git a/xCAT-test/bats/go_xcat_genesis_package_names.bats b/xCAT-test/bats/go_xcat_genesis_package_names.bats
index 68913d0c2..5da69f552 100644
--- a/xCAT-test/bats/go_xcat_genesis_package_names.bats
+++ b/xCAT-test/bats/go_xcat_genesis_package_names.bats
@@ -13,31 +13,26 @@ load 'helpers/shell_source'
setup()
{
- go_xcat_require_source
+ GO_XCAT_SOURCE="${XCAT_TEST_GO_XCAT:-$(go_xcat_default_source)}"
+ export GO_XCAT_SOURCE
SCRIPTS_DEBIAN="$(repo_path 'xCAT-genesis-scripts/debian')"
SPEC="$(repo_path 'xCAT-genesis-base/xCAT-genesis-base.spec')"
- [ -d "$SCRIPTS_DEBIAN" ] || skip "$SCRIPTS_DEBIAN is required"
- [ -r "$SPEC" ] || skip "$SPEC is required"
+ [ -r "$GO_XCAT_SOURCE" ] || return 1
+ [ -d "$SCRIPTS_DEBIAN" ] || return 1
+ [ -r "$SPEC" ] || return 1
export SCRIPTS_DEBIAN SPEC
}
-# Run the array definitions of go-xcat and print the two lists it built, one per line.
package_lists()
{
- local want_dpkg="$1" list_body
- list_body="$(awk '
- /^GO_XCAT_INSTALL_LIST=\(/ { copy = 1 }
- /^PATH=/ { exit }
- copy { print }
- ' "$GO_XCAT_SOURCE")"
- [ -n "$list_body" ] || { echo 'go-xcat package arrays not found' >&2; return 3; }
+ local want_dpkg="$1"
(
if [ "$want_dpkg" = 1 ]; then
dpkg() { :; }
fi
# A real dpkg on the build host would select the deb branch on every run.
PATH=""
- eval "$list_body"
+ source "$GO_XCAT_SOURCE" || exit 70
printf 'install %s\n' "${GO_XCAT_INSTALL_LIST[*]}"
printf 'uninstall %s\n' "${GO_XCAT_UNINSTALL_LIST[*]}"
)
diff --git a/xCAT-test/unit/destiny_genesis_architecture.t b/xCAT-test/unit/destiny_genesis_architecture.t
index e98aa678d..4204757f0 100644
--- a/xCAT-test/unit/destiny_genesis_architecture.t
+++ b/xCAT-test/unit/destiny_genesis_architecture.t
@@ -5,27 +5,26 @@ use warnings;
use File::Path qw(make_path);
use File::Temp qw(tempdir);
use FindBin;
+use lib "$FindBin::Bin/../lib";
+use lib "$FindBin::Bin/../../perl-xCAT";
+use lib "$FindBin::Bin/../../xCAT-server/lib/perl";
use Test::More;
-
-my $source = "$FindBin::Bin/../../xCAT-server/lib/xcat/plugins/destiny.pm";
-open(my $source_fh, '<', $source) or die "open $source: $!";
-my $content = do { local $/; <$source_fh> };
-close($source_fh) or die "close $source: $!";
-
-my @routines;
-for my $name (qw(_genesis_boot_arch _genesis_uses_power_console)) {
- my ($routine) = $content =~ /^(sub \Q$name\E\s*\{.*?^\})/ms;
- BAIL_OUT("could not extract $name from destiny.pm") unless $routine;
- push(@routines, $routine);
-}
-eval join("\n", @routines); ## no critic (BuiltinFunctions::ProhibitStringyEval)
-BAIL_OUT("could not load Genesis architecture helpers: $@") if $@;
+use XCAT::Test::File qw(repo_path);
my $tftp = tempdir(CLEANUP => 1);
-make_path("$tftp/xcat");
+$ENV{XCATROOT} = repo_path('xCAT-server');
+$ENV{XCATCFG} = "$tftp/config";
+make_path("$tftp/xcat", $ENV{XCATCFG});
+require xCAT::TableUtils;
+{
+ no warnings qw(redefine once);
+ local *xCAT::TableUtils::get_site_attribute = sub { return (0); };
+ local $INC{'xCAT_monitoring/monitorctrl.pm'} = __FILE__;
+ require(repo_path('xCAT-server/lib/xcat/plugins/destiny.pm'));
+}
is(
- _genesis_boot_arch($tftp, 'ppc64le'),
+ xCAT_plugin::destiny::_genesis_boot_arch($tftp, 'ppc64le'),
'ppc64',
'ppc64le keeps the legacy POWER fallback when no exact image exists',
);
@@ -35,7 +34,7 @@ open(my $marker_fh, '>', "$tftp/xcat/genesis.exact-arch.ppc64")
close($marker_fh) or die "close exact POWER marker: $!";
is(
- _genesis_boot_arch($tftp, 'ppc64le'),
+ xCAT_plugin::destiny::_genesis_boot_arch($tftp, 'ppc64le'),
'ppc64le',
'ppc64le does not fall back to a canonical big-endian ppc64 image',
);
@@ -47,25 +46,21 @@ open(my $kernel_fh, '>', "$tftp/xcat/genesis.kernel.ppc64le")
close($kernel_fh) or die "close exact POWER kernel: $!";
is(
- _genesis_boot_arch($tftp, 'ppc64le'),
+ xCAT_plugin::destiny::_genesis_boot_arch($tftp, 'ppc64le'),
'ppc64le',
'ppc64le uses the exact OpenEmbedded boot artifact',
);
is(
- _genesis_boot_arch($tftp, 'ppc64el'),
+ xCAT_plugin::destiny::_genesis_boot_arch($tftp, 'ppc64el'),
'ppc64le',
'the Debian spelling resolves to the exact ppc64le artifact',
);
-is(_genesis_boot_arch($tftp, 'x86_64'), 'x86_64', 'other architectures are unchanged');
+is(xCAT_plugin::destiny::_genesis_boot_arch($tftp, 'x86_64'), 'x86_64', 'other architectures are unchanged');
-ok(_genesis_uses_power_console('ppc64'), 'legacy POWER uses the hypervisor console');
-ok(_genesis_uses_power_console('ppc64le'), 'ppc64le uses the hypervisor console');
-ok(!_genesis_uses_power_console('x86_64'), 'x86_64 keeps the serial console path');
-
-like(
- $content,
- qr/my \$arch = _genesis_boot_arch\(\$tftpdir, \$ent->\{arch\}\);/,
- 'destiny applies the tested architecture selection to nodeset',
-);
+ok(xCAT_plugin::destiny::_genesis_uses_power_console('ppc64'), 'legacy POWER uses the hypervisor console');
+ok(xCAT_plugin::destiny::_genesis_uses_power_console('ppc64le'), 'ppc64le uses the hypervisor console');
+for my $arch (qw(x86_64 aarch64 s390x riscv64 ppc64el ppc64lex)) {
+ ok(!xCAT_plugin::destiny::_genesis_uses_power_console($arch), "$arch does not select a POWER console");
+}
done_testing();
diff --git a/xCAT-test/unit/xcatconfig_genesis_openembedded.t b/xCAT-test/unit/xcatconfig_genesis_openembedded.t
index 59c8fc3e7..360d97564 100644
--- a/xCAT-test/unit/xcatconfig_genesis_openembedded.t
+++ b/xCAT-test/unit/xcatconfig_genesis_openembedded.t
@@ -1,27 +1,39 @@
#!/usr/bin/env perl
use strict;
use warnings;
+no warnings 'once';
use File::Path qw(make_path remove_tree);
use File::Temp qw(tempdir);
use FindBin;
+use lib "$FindBin::Bin/../lib";
+use lib "$FindBin::Bin/../../perl-xCAT";
+use lib "$FindBin::Bin/../../xCAT-server/lib/perl";
use Test::More;
+use XCAT::Test::File qw(repo_path);
-my $source = "$FindBin::Bin/../../xCAT-server/sbin/xcatconfig";
-open(my $source_fh, '<', $source) or die "open $source: $!";
-my $content = do { local $/; <$source_fh> };
-close($source_fh) or die "close $source: $!";
-
-my @routines;
-for my $name (qw(_installed_genesis_architectures _genesis_architectures_to_build)) {
- my ($routine) = $content =~ /^(sub \Q$name\E\s*\{.*?^\})/ms;
- BAIL_OUT("could not extract $name from xcatconfig") unless $routine;
- push(@routines, $routine);
+BEGIN {
+ *CORE::GLOBAL::exit = sub { die bless { status => $_[0] || 0 }, 'XcatconfigTestExit'; };
}
-eval join("\n", @routines); ## no critic (BuiltinFunctions::ProhibitStringyEval)
-BAIL_OUT("could not load Genesis architecture helpers: $@") if $@;
my $tmpdir = tempdir(CLEANUP => 1);
+$ENV{XCATROOT} = repo_path('xCAT-server');
+$ENV{XCATCFG} = "$tmpdir/config";
+make_path($ENV{XCATCFG});
+my ($help, $error);
+{
+ local @ARGV = ('--help');
+ open(my $out, '>', \$help) or die $!;
+ local *STDOUT = $out;
+ do(repo_path('xCAT-server/sbin/xcatconfig'));
+ $error = $@;
+}
+is(ref($error), 'XcatconfigTestExit', 'the complete CLI reaches its help exit');
+is(ref($error) ? $error->{status} : undef, 0, 'help exits successfully');
+like($help, qr/xcatconfig/, 'the complete CLI prints usage');
+die "Cannot load xcatconfig: $error" unless ref($error) eq 'XcatconfigTestExit' && !$error->{status};
+$::osname = 'Linux';
+
make_path(
"$tmpdir/share/xcat/netboot/genesis/ppc64/fs",
"$tmpdir/share/xcat/netboot/genesis/x86_64/fs",