Eight of the parity decisions in the spec's Appendix A, where ISC dhcpd and
Kea answered the same frame differently and the operator never chose which
backend they got.
ISC gains two branches its if/else chain never had, so the client falls
through to /yaboot no longer:
- 0x000c ppc64 is given /boot/grub2/grub2.ppc. yaboot is not a UEFI
loader and cannot boot one of these machines (decision 2).
- 0x0010 is the same x86-64 UEFI firmware and the same loader as 0x0007,
announced by a machine set to fetch it over HTTP (decision 3).
Kea gains what ISC has always had:
- Etherboot, which predates option 93 and says what it is in option 60
alone, is recognised and given the BIOS loader (decision 10).
- onie_vendor is answered per subnet, not only per node: a switch
announces it on its first boot, before anyone has defined it as a node
(decision 11).
- A client nothing else recognises is given /yaboot. Kea has no else, so
the condition is the negation of every architecture and vendor class
another rule answers, rather than a dependence on class ordering
(decision 7).
- netboot=nimol is given /vios/nodes/<node> (decision 6).
and drops two answers ISC never gave:
- No BIOS loader on disk no longer means pxelinux.0 in its place. Naming
a file that is not there costs the client a timeout it cannot diagnose,
and a different loader boots something nobody asked for; the class is
simply not written (decision 8).
- netboot=petitboot sends the conf-file and nothing else. petitboot acts
on a boot file name when it sees one, so naming one as well sent the
machine after a TFTP fetch that never happens on ISC (decision 12).
xCAT-test/unit
Unit tests. These run against the source tree only -- no xCAT installation, no running daemons, no management node.
They are executed on every pull request by the xcat_test GitHub Actions workflow,
which calls run_unit_tests() in github_action_xcat_test.pl:
prove -r xCAT-test/unit
You can run exactly the same thing from a clean checkout:
cd <xcat-core checkout>
prove -r xCAT-test/unit
What belongs here
A test belongs in unit/ when everything it needs is in the checkout: plugin and
library sources, kickstart/preseed/subiquity templates, postscripts, packaging
metadata. Such a test asserts on rendered output or module logic and reaches the
repository root through FindBin:
use FindBin;
use lib "$FindBin::Bin/../../perl-xCAT";
use lib "$FindBin::Bin/../../xCAT-server/lib/perl";
Because of those FindBin paths the tests only work from a source tree. The copy
installed under /opt/xcat/share/xcat/tools/autotest/unit is not a substitute --
../.. resolves to /opt/xcat/share/xcat/tools there and the tests die or silently
skip. The CI takes a copy of the checkout before the build for this reason; see
preserve_source_tree().
What does not belong here
Anything that needs an installed xCAT, a populated /install, a real service binary
or a live daemon. Those go in ../integration and run on
a management node through xcattest. Both suites run on every pull request -- the
workflow installs xCAT on the runner and then runs the ci_test cases against it --
so putting a test in integration/ does not cost it CI coverage. What differs is what
each suite is allowed to depend on, and that unit tests also run standalone from a
bare checkout with no xCAT at all.
Shell-script unit tests belong in ../bats
and run with BATS. Do not add Perl .t tests that grep shell source when the
behavior can be exercised by sourcing a shell library or script and shadowing the
external commands it calls.
The distinction matters because a test that needs an absent environment does not fail
-- it calls plan skip_all and reports as skipped. A handful of those in a suite of
several hundred assertions is easy to stop reading. Keeping the two kinds in separate
directories means a skip in unit/ is a real signal rather than routine noise.
Guarding on a source file, on the other hand, is fine and common here:
plan skip_all => "compute.subiquity.tmpl not found" unless -f $tmpl_path;
That guard never fires when the tree is intact.