issue 1841/S15: put the booted kernel first when GRUB's menu is generated again, so the fallback kernel, sorted first by version, never becomes the default entry (ADR 0508 §9)

This commit is contained in:
2026-10-22 17:49:21 +02:00
parent f40269caec
commit 76a0a726f0
3 changed files with 54 additions and 5 deletions
@@ -78,7 +78,8 @@ func newBootBed(t *testing.T) bootBed {
}
write(t, b.script, content, 0o755)
write(t, b.root+"/proc/cmdline", bootedCmdline, 0o644)
write(t, filepath.Join(b.bin, "grub-mkconfig"), "#!/bin/sh\necho \"$@\" >>"+b.mkconfig+"\n", 0o755)
// the stand-in grub-mkconfig records the kernel it was told to put first, then its arguments.
write(t, filepath.Join(b.bin, "grub-mkconfig"), "#!/bin/sh\necho \"top=$GRUB_TOP_LEVEL $@\" >>"+b.mkconfig+"\n", 0o755)
return b
}
@@ -164,11 +165,37 @@ func TestAGrubMachineIsGeneratedAgainOnlyWhenItsKernelsChanged(t *testing.T) {
t.Fatalf("changed: %v %s", err, out)
}
raw, _ := os.ReadFile(b.mkconfig)
if string(raw) != "-o "+filepath.Join(b.root, "boot/grub/grub.cfg")+"\n" {
if string(raw) != "top=/boot/vmlinuz-linux -o "+filepath.Join(b.root, "boot/grub/grub.cfg")+"\n" {
t.Fatalf("grub-mkconfig was asked %q", raw)
}
}
// ADR 0508 §9: GRUB's menu lists kernels in reverse version order, so linux-lts would come first and become the
// default entry (GRUB_DEFAULT=0); the kernel the machine booted is put first, and the fallback kernel never.
func TestGrubKeepsTheBootedKernelFirstAndNeverTheFallback(t *testing.T) {
for name, c := range map[string]struct{ cmdline, want string }{
"booted from the default kernel": {"BOOT_IMAGE=/vmlinuz-linux root=UUID=x rw\n", "top=/boot/vmlinuz-linux"},
"booted from a grub device path": {"BOOT_IMAGE=(hd0,msdos1)/vmlinuz-linux-zen root=UUID=x rw\n", "top=/boot/vmlinuz-linux-zen"},
"booted from the fallback kernel": {"BOOT_IMAGE=/vmlinuz-linux-lts root=UUID=x rw\n", "top=/boot/vmlinuz-linux"},
"no image on the command line": {"root=UUID=x rw\n", "top=/boot/vmlinuz-linux"},
"an image no longer in /boot": {"BOOT_IMAGE=/vmlinuz-linux-gone root=UUID=x rw\n", "top=/boot/vmlinuz-linux"},
} {
b := newBootBed(t)
b.put(t, "boot/grub/grub.cfg", grubMenu)
b.put(t, "proc/cmdline", c.cmdline)
for _, k := range []string{"vmlinuz-linux", "vmlinuz-linux-lts", "vmlinuz-linux-zen"} {
b.put(t, "boot/"+k, "k")
}
if out, err := b.run(t); err != nil {
t.Fatalf("%s: %v %s", name, err, out)
}
raw, _ := os.ReadFile(b.mkconfig)
if !strings.HasPrefix(string(raw), c.want+" -o ") {
t.Errorf("%s: grub-mkconfig was asked %q, want %s first", name, raw, c.want)
}
}
}
func TestAMachineWithNoLoaderFailsLoudly(t *testing.T) {
b := newBootBed(t)
out, err := b.run(t)