summaryrefslogtreecommitdiffstats
path: root/test/test-fstab-generator.sh
blob: af8fa7c226d576a4305aac9b893ed383d82ba652 (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
#!/usr/bin/env bash
# SPDX-License-Identifier: LGPL-2.1-or-later
set -eux
shopt -s nullglob
shopt -s globstar

if [[ -n "${1:-}" ]]; then
    generator=$1
elif [[ -x /usr/lib/systemd/system-generators/systemd-fstab-generator ]]; then
    generator=/usr/lib/systemd/system-generators/systemd-fstab-generator
elif [[ -x /lib/systemd/system-generators/systemd-fstab-generator ]]; then
    generator=/lib/systemd/system-generators/systemd-fstab-generator
else
    exit 1
fi

src="$(dirname "$0")/testdata/test-fstab-generator"

# fsck(8) is located in /usr/sbin on Debian
PATH=$PATH:/usr/sbin

# systemd-pcrfs@.service could be enabled or not, depending on the host state
# of the host system. Override the measurement to avoid the issue.
export SYSTEMD_FORCE_MEASURE=0

test_one() (
    local initrd input out exp i j k dir fname expf

    input=${1?}
    initrd=${2?}

    : "*** Running $input (initrd=$initrd)"

    out=$(mktemp --tmpdir --directory "test-fstab-generator.XXXXXXXXXX")
    # shellcheck disable=SC2064
    trap "rm -rf '$out'" EXIT INT QUIT PIPE

    exp="${input%.input}.expected"
    if [[ "${input##*/}" =~ swap ]] && systemd-detect-virt --container >/dev/null; then
        exp="${exp}.container"
    fi
    if [[ "$initrd" == no ]]; then
        exp="${exp}.sysroot"
    fi

    if [[ "${input##*/}" =~ \.fstab\.input ]]; then
        SYSTEMD_LOG_LEVEL=debug SYSTEMD_IN_INITRD="$initrd" SYSTEMD_SYSFS_CHECK=no SYSTEMD_PROC_CMDLINE="fstab=yes root=fstab" SYSTEMD_FSTAB="$input" SYSTEMD_SYSROOT_FSTAB="/dev/null" $generator "$out" "$out" "$out"
    else
        SYSTEMD_LOG_LEVEL=debug SYSTEMD_IN_INITRD="$initrd" SYSTEMD_SYSFS_CHECK=no SYSTEMD_PROC_CMDLINE="fstab=no $(cat "$input")" $generator "$out" "$out" "$out"
    fi

    # The option x-systemd.growfs creates symlink to system's systemd-growfs@.service in .mount.wants directory.
    # Also, when $initrd is no, symlink to systemd-remount-fs.service is created.
    # The system that the test is currently running on may not have or may have outdated unit file.
    # Let's replace the symlink with an empty file.
    for i in "$out"/*/systemd-growfs@*.service "$out"/local-fs.target.wants/systemd-remount-fs.service; do
        [[ -L "$i" ]] || continue
        rm "$i"
        touch "$i"
    done

    if [[ "${input##*/}" =~ \.fstab\.input ]]; then
        for i in "$out"/*.{automount,mount,swap}; do
            sed -i -e 's:SourcePath=.*$:SourcePath=/etc/fstab:' "$i"
        done
    fi

    # .deb packager seems to dislike files named with backslash. So, as a workaround, we store files
    # without backslash in .expected.
    for i in "$out"/**/*\\*.{mount,swap}; do
        k="${i//\\/}"
        if [[ "$i" != "$k" ]]; then
            if [[ -f "$i" ]]; then
                mv "$i" "$k"
            elif [[ -L "$i" ]]; then
                dest=$(readlink "$i")
                rm "$i"
                ln -s "${dest//\\/}" "$k"
            fi
        fi
    done

    # We do not store empty directory.
    if [[ -z "$(ls -A "$out")" && ! -d "$exp" ]]; then
        return 0
    fi

    # We store empty files rather than dead symlinks, so that they don't get pruned when packaged up, so compare
    # the list of filenames rather than their content
    if ! diff -u <(find "$out" -printf '%P\n' | sort) <(find "$exp" -printf '%P\n' | sort); then
        : "**** Unexpected output for $input (initrd=$initrd)"
        return 1
    fi

    # Check the main units.
    if ! diff -u "$out" "$exp"; then
        : "**** Unexpected output for $input (initrd=$initrd)"
        return 1
    fi

    # Also check drop-ins.
    for i in "$out"/*; do
        [[ -d "$i" ]] || continue

        dir="${i##*/}"

        for j in "$i"/*; do
            fname="${j##*/}"
            expf="$exp/$dir/$fname"

            if [[ -L "$j" && ! -e "$j" ]]; then
                # For dead symlink, we store an empty file.
                if [[ ! -e "$expf" || -n "$(cat "$expf")" ]]; then
                    : "**** Unexpected symlink $j created by $input (initrd=$initrd)"
                    return 1
                fi
                continue
            fi

            if ! diff -u "$j" "$expf"; then
                : "**** Unexpected output in $j for $input (initrd=$initrd)"
                return 1
            fi
        done
    done

    return 0
)

for f in "$src"/test-*.input; do
    # If /mnt is a symlink, then the expected output from this
    # test scenario will not match the actual output
    if test "$f" = "$src/test-18-options.fstab.input" -a "$(readlink /mnt)" != "/mnt"
    then
        echo "Skip $f because /mnt is a symlink"
        continue
    fi

    test_one "$f" yes
    test_one "$f" no
done