aboutsummaryrefslogtreecommitdiff
path: root/tests/unit/test_disk.bats
blob: 1b3cfba3a083e781c7035d29388797c7f2e1bb62 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
#!/usr/bin/env bats
# Unit tests for installer/lib/disk.sh
#
# Coverage scope: pure partition-path helpers (get_efi_partition,
# get_root_partition) plus the partition_disks orchestration shape
# (which globals get populated, which destructive tools get invoked,
# how often). The destructive tools themselves (sgdisk, wipefs,
# partprobe, mkfs.fat) and the interactive select_disks (fzf) are
# validated by VM integration per the project's testing-strategy.org
# policy.

setup() {
    # shellcheck disable=SC1091
    source "${BATS_TEST_DIRNAME}/../../installer/lib/common.sh"
    # shellcheck disable=SC1091
    source "${BATS_TEST_DIRNAME}/../../installer/lib/disk.sh"
}

#############################
# get_efi_partition
#############################

@test "get_efi_partition: SATA disk gets numeric suffix 1" {
    run get_efi_partition /dev/sda
    [ "$status" -eq 0 ]
    [ "$output" = "/dev/sda1" ]
}

@test "get_efi_partition: virtio disk gets numeric suffix 1" {
    run get_efi_partition /dev/vda
    [ "$status" -eq 0 ]
    [ "$output" = "/dev/vda1" ]
}

@test "get_efi_partition: NVMe disk gets p1 suffix" {
    run get_efi_partition /dev/nvme0n1
    [ "$status" -eq 0 ]
    [ "$output" = "/dev/nvme0n1p1" ]
}

@test "get_efi_partition: NVMe with multi-namespace disk gets p1 suffix" {
    run get_efi_partition /dev/nvme1n2
    [ "$status" -eq 0 ]
    [ "$output" = "/dev/nvme1n2p1" ]
}

@test "get_efi_partition: empty input documents current behavior" {
    # Empty input misses the nvme regex so the bare-suffix branch fires,
    # producing just "1". This pins the existing behavior; the function
    # is never called with empty in production but pinning catches a
    # change in suffix-rule logic.
    run get_efi_partition ""
    [ "$status" -eq 0 ]
    [ "$output" = "1" ]
}

#############################
# get_root_partition
#############################

@test "get_root_partition: SATA disk gets numeric suffix 2" {
    run get_root_partition /dev/sda
    [ "$status" -eq 0 ]
    [ "$output" = "/dev/sda2" ]
}

@test "get_root_partition: NVMe disk gets p2 suffix" {
    run get_root_partition /dev/nvme0n1
    [ "$status" -eq 0 ]
    [ "$output" = "/dev/nvme0n1p2" ]
}

@test "get_root_partition: virtio disk gets numeric suffix 2" {
    run get_root_partition /dev/vdb
    [ "$status" -eq 0 ]
    [ "$output" = "/dev/vdb2" ]
}

#############################
# partition_disks (orchestration)
#############################
# partition_disks reads SELECTED_DISKS, dispatches the per-disk
# layout (sgdisk + wipefs + mkfs.fat) on FILESYSTEM, and populates
# EFI_PARTS + ROOT_PARTS for downstream callers (create_zfs_pool,
# btrfs_open_encryption, sync_efi_partitions, fstab generation).
#
# The destructive system tools (sgdisk, wipefs, partprobe, mkfs.fat)
# are mocked to capture invocation shape only — actual partition
# behavior is validated by VM integration per testing-strategy.org.

partition_disks_setup() {
    SELECTED_DISKS=()
    EFI_PARTS=()
    ROOT_PARTS=()
    CALLS=()
    sgdisk()    { CALLS+=("sgdisk $*");   return 0; }
    wipefs()    { CALLS+=("wipefs $*");   return 0; }
    partprobe() { CALLS+=("partprobe $*"); return 0; }
    mkfs.fat()  { CALLS+=("mkfs.fat $*");  return 0; }
    sleep()     { :; }
    info()      { :; }
    step()      { :; }
    error()     { CALLS+=("error $*"); return 1; }
}

@test "partition_disks: populates EFI_PARTS and ROOT_PARTS for single SATA disk" {
    partition_disks_setup
    SELECTED_DISKS=(/dev/sda)
    FILESYSTEM=zfs

    partition_disks

    [ "${#EFI_PARTS[@]}" -eq 1 ]
    [ "${#ROOT_PARTS[@]}" -eq 1 ]
    [ "${EFI_PARTS[0]}" = "/dev/sda1" ]
    [ "${ROOT_PARTS[0]}" = "/dev/sda2" ]
}

@test "partition_disks: NVMe disk gets p1/p2 suffixes in globals" {
    partition_disks_setup
    SELECTED_DISKS=(/dev/nvme0n1)
    FILESYSTEM=zfs

    partition_disks

    [ "${EFI_PARTS[0]}" = "/dev/nvme0n1p1" ]
    [ "${ROOT_PARTS[0]}" = "/dev/nvme0n1p2" ]
}

@test "partition_disks: multi-disk SATA populates both arrays in order" {
    partition_disks_setup
    SELECTED_DISKS=(/dev/sda /dev/sdb /dev/sdc)
    FILESYSTEM=zfs

    partition_disks

    [ "${#EFI_PARTS[@]}" -eq 3 ]
    [ "${#ROOT_PARTS[@]}" -eq 3 ]
    [ "${EFI_PARTS[0]}" = "/dev/sda1" ]
    [ "${EFI_PARTS[1]}" = "/dev/sdb1" ]
    [ "${EFI_PARTS[2]}" = "/dev/sdc1" ]
    [ "${ROOT_PARTS[0]}" = "/dev/sda2" ]
    [ "${ROOT_PARTS[1]}" = "/dev/sdb2" ]
    [ "${ROOT_PARTS[2]}" = "/dev/sdc2" ]
}

@test "partition_disks: mixed SATA + NVMe applies correct suffix per disk" {
    partition_disks_setup
    SELECTED_DISKS=(/dev/sda /dev/nvme0n1)
    FILESYSTEM=zfs

    partition_disks

    [ "${EFI_PARTS[0]}" = "/dev/sda1" ]
    [ "${EFI_PARTS[1]}" = "/dev/nvme0n1p1" ]
    [ "${ROOT_PARTS[0]}" = "/dev/sda2" ]
    [ "${ROOT_PARTS[1]}" = "/dev/nvme0n1p2" ]
}

@test "partition_disks: ZFS dispatch passes BF00 root type to sgdisk" {
    partition_disks_setup
    SELECTED_DISKS=(/dev/sda)
    FILESYSTEM=zfs

    partition_disks

    [[ " ${CALLS[*]} " == *"sgdisk -n 2:0:0 -t 2:BF00"* ]]
}

@test "partition_disks: Btrfs dispatch passes 8300 root type to sgdisk" {
    partition_disks_setup
    SELECTED_DISKS=(/dev/sda)
    FILESYSTEM=btrfs

    partition_disks

    [[ " ${CALLS[*]} " == *"sgdisk -n 2:0:0 -t 2:8300"* ]]
}

@test "partition_disks: invokes wipefs -af on each disk" {
    partition_disks_setup
    SELECTED_DISKS=(/dev/sda /dev/sdb)
    FILESYSTEM=zfs

    partition_disks

    local count
    count=$(printf '%s\n' "${CALLS[@]}" | grep -c '^wipefs -af ')
    [ "$count" -eq 2 ]
    [[ " ${CALLS[*]} " == *"wipefs -af /dev/sda"* ]]
    [[ " ${CALLS[*]} " == *"wipefs -af /dev/sdb"* ]]
}

@test "partition_disks: invokes mkfs.fat once per EFI partition with EFI<i> label" {
    partition_disks_setup
    SELECTED_DISKS=(/dev/sda /dev/sdb)
    FILESYSTEM=zfs

    partition_disks

    local count
    count=$(printf '%s\n' "${CALLS[@]}" | grep -c '^mkfs.fat ')
    [ "$count" -eq 2 ]
    [[ " ${CALLS[*]} " == *"mkfs.fat -F32 -n EFI0 /dev/sda1"* ]]
    [[ " ${CALLS[*]} " == *"mkfs.fat -F32 -n EFI1 /dev/sdb1"* ]]
}

@test "partition_disks: re-initializes globals on second call" {
    partition_disks_setup
    SELECTED_DISKS=(/dev/sda /dev/sdb)
    FILESYSTEM=zfs

    partition_disks
    [ "${#EFI_PARTS[@]}" -eq 2 ]

    SELECTED_DISKS=(/dev/sdc)
    partition_disks

    [ "${#EFI_PARTS[@]}" -eq 1 ]
    [ "${#ROOT_PARTS[@]}" -eq 1 ]
    [ "${EFI_PARTS[0]}" = "/dev/sdc1" ]
}

@test "partition_disks: empty SELECTED_DISKS calls error and skips work" {
    partition_disks_setup
    SELECTED_DISKS=()
    FILESYSTEM=zfs

    partition_disks || true

    [[ " ${CALLS[*]} " == *"error partition_disks: SELECTED_DISKS is empty"* ]]
    [[ " ${CALLS[*]} " != *"sgdisk"* ]]
    [[ " ${CALLS[*]} " != *"wipefs"* ]]
}