aboutsummaryrefslogtreecommitdiff
path: root/filesystem/mountpoint_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'filesystem/mountpoint_test.go')
-rw-r--r--filesystem/mountpoint_test.go226
1 files changed, 226 insertions, 0 deletions
diff --git a/filesystem/mountpoint_test.go b/filesystem/mountpoint_test.go
index 73904a2..d21ba48 100644
--- a/filesystem/mountpoint_test.go
+++ b/filesystem/mountpoint_test.go
@@ -17,9 +17,19 @@
* the License.
*/
+// Note: these tests assume the existence of some well-known directories and
+// devices: /mnt, /home, /tmp, and /dev/loop0. This is because the mountpoint
+// loading code only retains mountpoints on valid directories, and only retains
+// device names for valid device nodes.
+
package filesystem
import (
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "strings"
"testing"
)
@@ -29,6 +39,222 @@ func TestLoadMountInfo(t *testing.T) {
}
}
+// Lock the mount maps so that concurrent tests don't interfere with each other.
+func beginLoadMountInfoTest() {
+ mountMutex.Lock()
+}
+
+func endLoadMountInfoTest() {
+ // Invalidate the fake mount information in case a test runs later which
+ // needs the real mount information.
+ mountsInitialized = false
+ mountMutex.Unlock()
+}
+
+func loadMountInfoFromString(str string) {
+ readMountInfo(strings.NewReader(str))
+}
+
+func mountForDevice(deviceNumberStr string) *Mount {
+ deviceNumber, _ := newDeviceNumberFromString(deviceNumberStr)
+ return mountsByDevice[deviceNumber]
+}
+
+// Test basic loading of a single mountpoint.
+func TestLoadMountInfoBasic(t *testing.T) {
+ var mountinfo = `
+15 0 259:3 / / rw,relatime shared:1 - ext4 /dev/root rw,data=ordered
+`
+ beginLoadMountInfoTest()
+ defer endLoadMountInfoTest()
+ loadMountInfoFromString(mountinfo)
+ if len(mountsByDevice) != 1 {
+ t.Error("Loaded wrong number of mounts")
+ }
+ mnt := mountForDevice("259:3")
+ if mnt == nil {
+ t.Fatal("Failed to load mount")
+ }
+ if mnt.Path != "/" {
+ t.Error("Wrong path")
+ }
+ if mnt.FilesystemType != "ext4" {
+ t.Error("Wrong filesystem type")
+ }
+ if mnt.DeviceNumber.String() != "259:3" {
+ t.Error("Wrong device number")
+ }
+ if mnt.BindMnt {
+ t.Error("Wrong bind mount flag")
+ }
+ if mnt.ReadOnly {
+ t.Error("Wrong readonly flag")
+ }
+}
+
+// Test that Mount.Device is set to the mountpoint's source device if
+// applicable, otherwise it is set to the empty string.
+func TestLoadSourceDevice(t *testing.T) {
+ var mountinfo = `
+15 0 7:0 / / rw shared:1 - foo /dev/loop0 rw,data=ordered
+31 15 0:27 / /tmp rw,nosuid,nodev shared:17 - tmpfs tmpfs rw
+`
+ beginLoadMountInfoTest()
+ defer endLoadMountInfoTest()
+ loadMountInfoFromString(mountinfo)
+ mnt := mountForDevice("7:0")
+ if mnt.Device != "/dev/loop0" {
+ t.Error("mnt.Device wasn't set to source device")
+ }
+ mnt = mountForDevice("0:27")
+ if mnt.Device != "" {
+ t.Error("mnt.Device wasn't set to empty string for an invalid device")
+ }
+}
+
+// Test that non-directory mounts are ignored.
+func TestNondirectoryMountsIgnored(t *testing.T) {
+ beginLoadMountInfoTest()
+ defer endLoadMountInfoTest()
+ file, err := ioutil.TempFile("", "fscrypt_regfile")
+ if err != nil {
+ t.Fatal(err)
+ }
+ file.Close()
+ defer os.Remove(file.Name())
+
+ mountinfo := fmt.Sprintf("15 0 259:3 /foo %s rw,relatime shared:1 - ext4 /dev/root rw", file.Name())
+ loadMountInfoFromString(mountinfo)
+ if len(mountsByDevice) != 0 {
+ t.Error("Non-directory mount wasn't ignored")
+ }
+}
+
+// Test that when multiple mounts are on one directory, the last is the one
+// which is kept.
+func TestNonLatestMountsIgnored(t *testing.T) {
+ mountinfo := `
+15 0 259:3 / / rw shared:1 - ext4 /dev/root rw
+15 0 259:3 / / rw shared:1 - f2fs /dev/root rw
+15 0 259:3 / / rw shared:1 - ubifs /dev/root rw
+`
+ beginLoadMountInfoTest()
+ defer endLoadMountInfoTest()
+ loadMountInfoFromString(mountinfo)
+ mnt := mountForDevice("259:3")
+ if mnt.FilesystemType != "ubifs" {
+ t.Error("Last mount didn't supersede previous ones")
+ }
+}
+
+// Test that escape sequences in the mountinfo file are unescaped correctly.
+func TestLoadMountWithSpecialCharacters(t *testing.T) {
+ tempDir, err := ioutil.TempDir("", "fscrypt")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(tempDir)
+ tempDir, err = filepath.Abs(tempDir)
+ if err != nil {
+ t.Fatal(err)
+ }
+ mountpoint := filepath.Join(tempDir, "/My Directory\t\n\\")
+ if err := os.Mkdir(mountpoint, 0700); err != nil {
+ t.Fatal(err)
+ }
+ mountinfo := fmt.Sprintf("15 0 259:3 / %s/My\\040Directory\\011\\012\\134 rw shared:1 - ext4 /dev/root rw", tempDir)
+
+ beginLoadMountInfoTest()
+ defer endLoadMountInfoTest()
+ loadMountInfoFromString(mountinfo)
+ mnt := mountForDevice("259:3")
+ if mnt.Path != mountpoint {
+ t.Fatal("Wrong mountpoint")
+ }
+}
+
+// Test parsing some invalid mountinfo lines.
+func TestLoadBadMountInfo(t *testing.T) {
+ mountinfos := []string{"a",
+ "a a a a a a a a a a a a a a a",
+ "a a a a a a a a a a a a - a a",
+ "15 0 BAD:3 / / rw,relatime shared:1 - ext4 /dev/root rw,data=ordered"}
+ beginLoadMountInfoTest()
+ defer endLoadMountInfoTest()
+ for _, mountinfo := range mountinfos {
+ loadMountInfoFromString(mountinfo)
+ if len(mountsByDevice) != 0 {
+ t.Error("Loaded mount from invalid mountinfo line")
+ }
+ }
+}
+
+// Test that the ReadOnly flag is set if the mount is readonly, even if the
+// filesystem is read-write.
+func TestLoadReadOnlyMount(t *testing.T) {
+ mountinfo := `
+222 15 259:3 / /mnt ro,relatime shared:1 - ext4 /dev/root rw,data=ordered
+`
+ beginLoadMountInfoTest()
+ defer endLoadMountInfoTest()
+ loadMountInfoFromString(mountinfo)
+ mnt := mountForDevice("259:3")
+ if !mnt.ReadOnly {
+ t.Error("Wrong readonly flag")
+ }
+}
+
+// Test that a read-write mount is preferred over a read-only mount.
+func TestReadWriteMountIsPreferredOverReadOnlyMount(t *testing.T) {
+ mountinfo := `
+222 15 259:3 / /home ro shared:1 - ext4 /dev/root rw
+222 15 259:3 / /mnt rw shared:1 - ext4 /dev/root rw
+222 15 259:3 / /tmp ro shared:1 - ext4 /dev/root rw
+`
+ beginLoadMountInfoTest()
+ defer endLoadMountInfoTest()
+ loadMountInfoFromString(mountinfo)
+ mnt := mountForDevice("259:3")
+ if mnt.Path != "/mnt" {
+ t.Error("Wrong mount was chosen")
+ }
+}
+
+// Test that a mount of the full filesystem is preferred over a bind mount.
+func TestFullMountIsPreferredOverBindMount(t *testing.T) {
+ mountinfo := `
+222 15 259:3 /subtree1 /home rw shared:1 - ext4 /dev/root rw
+222 15 259:3 / /mnt rw shared:1 - ext4 /dev/root rw
+222 15 259:3 /subtree2 /tmp rw shared:1 - ext4 /dev/root rw
+`
+ beginLoadMountInfoTest()
+ defer endLoadMountInfoTest()
+ loadMountInfoFromString(mountinfo)
+ mnt := mountForDevice("259:3")
+ if mnt.Path != "/mnt" {
+ t.Error("Wrong mount was chosen")
+ }
+}
+
+// Test that if a filesystem only has bind mounts, a nil mountsByDevice entry is
+// created.
+func TestLoadOnlyBindMounts(t *testing.T) {
+ mountinfo := `
+222 15 259:3 /foo /mnt ro,relatime shared:1 - ext4 /dev/root rw,data=ordered
+`
+ beginLoadMountInfoTest()
+ defer endLoadMountInfoTest()
+ loadMountInfoFromString(mountinfo)
+ deviceNumber, _ := newDeviceNumberFromString("259:3")
+ mnt, ok := mountsByDevice[deviceNumber]
+ if !ok {
+ t.Error("Entry should exist")
+ }
+ if mnt != nil {
+ t.Error("Entry should be nil")
+ }
+}
+
// Benchmarks how long it takes to update the mountpoint data
func BenchmarkLoadFirst(b *testing.B) {
for n := 0; n < b.N; n++ {