| // Copyright 2019 The Prometheus Authors |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| package procfs |
| |
| import ( |
| "reflect" |
| "testing" |
| ) |
| |
| func TestMountInfo(t *testing.T) { |
| tests := []struct { |
| name string |
| s string |
| mount *MountInfo |
| invalid bool |
| }{ |
| { |
| name: "Regular sysfs mounted at /sys", |
| s: "16 21 0:16 / /sys rw,nosuid,nodev,noexec,relatime shared:7 - sysfs sysfs rw", |
| invalid: false, |
| mount: &MountInfo{ |
| MountId: 16, |
| ParentId: 21, |
| MajorMinorVer: "0:16", |
| Root: "/", |
| MountPoint: "/sys", |
| Options: map[string]string{"rw": "", "nosuid": "", "nodev": "", "noexec": "", "relatime": ""}, |
| OptionalFields: map[string]string{"shared": "7"}, |
| FSType: "sysfs", |
| Source: "sysfs", |
| SuperOptions: map[string]string{"rw": ""}, |
| }, |
| }, |
| { |
| name: "Not enough information", |
| s: "hello", |
| invalid: true, |
| }, |
| { |
| name: "Tmpfs mounted at /run", |
| s: "225 20 0:39 / /run/user/112 rw,nosuid,nodev,relatime shared:177 - tmpfs tmpfs rw,size=405096k,mode=700,uid=112,gid=116", |
| mount: &MountInfo{ |
| MountId: 225, |
| ParentId: 20, |
| MajorMinorVer: "0:39", |
| Root: "/", |
| MountPoint: "/run/user/112", |
| Options: map[string]string{"rw": "", "nosuid": "", "nodev": "", "relatime": ""}, |
| OptionalFields: map[string]string{"shared": "177"}, |
| FSType: "tmpfs", |
| Source: "tmpfs", |
| SuperOptions: map[string]string{"rw": "", "size": "405096k", "mode": "700", "uid": "112", "gid": "116"}, |
| }, |
| invalid: false, |
| }, |
| { |
| name: "Tmpfs mounted at /run, but no optional values", |
| s: "225 20 0:39 / /run/user/112 rw,nosuid,nodev,relatime - tmpfs tmpfs rw,size=405096k,mode=700,uid=112,gid=116", |
| mount: &MountInfo{ |
| MountId: 225, |
| ParentId: 20, |
| MajorMinorVer: "0:39", |
| Root: "/", |
| MountPoint: "/run/user/112", |
| Options: map[string]string{"rw": "", "nosuid": "", "nodev": "", "relatime": ""}, |
| OptionalFields: nil, |
| FSType: "tmpfs", |
| Source: "tmpfs", |
| SuperOptions: map[string]string{"rw": "", "size": "405096k", "mode": "700", "uid": "112", "gid": "116"}, |
| }, |
| invalid: false, |
| }, |
| { |
| name: "Tmpfs mounted at /run, with multiple optional values", |
| s: "225 20 0:39 / /run/user/112 rw,nosuid,nodev,relatime shared:177 master:8 - tmpfs tmpfs rw,size=405096k,mode=700,uid=112,gid=116", |
| mount: &MountInfo{ |
| MountId: 225, |
| ParentId: 20, |
| MajorMinorVer: "0:39", |
| Root: "/", |
| MountPoint: "/run/user/112", |
| Options: map[string]string{"rw": "", "nosuid": "", "nodev": "", "relatime": ""}, |
| OptionalFields: map[string]string{"shared": "177", "master": "8"}, |
| FSType: "tmpfs", |
| Source: "tmpfs", |
| SuperOptions: map[string]string{"rw": "", "size": "405096k", "mode": "700", "uid": "112", "gid": "116"}, |
| }, |
| invalid: false, |
| }, |
| { |
| name: "Tmpfs mounted at /run, with a mixture of valid and invalid optional values", |
| s: "225 20 0:39 / /run/user/112 rw,nosuid,nodev,relatime shared:177 master:8 foo:bar - tmpfs tmpfs rw,size=405096k,mode=700,uid=112,gid=116", |
| mount: &MountInfo{ |
| MountId: 225, |
| ParentId: 20, |
| MajorMinorVer: "0:39", |
| Root: "/", |
| MountPoint: "/run/user/112", |
| Options: map[string]string{"rw": "", "nosuid": "", "nodev": "", "relatime": ""}, |
| OptionalFields: map[string]string{"shared": "177", "master": "8"}, |
| FSType: "tmpfs", |
| Source: "tmpfs", |
| SuperOptions: map[string]string{"rw": "", "size": "405096k", "mode": "700", "uid": "112", "gid": "116"}, |
| }, |
| invalid: false, |
| }, |
| { |
| name: "CIFS mounted at /with/a-hyphen", |
| s: "454 29 0:87 / /with/a-hyphen rw,relatime shared:255 - cifs //remote-storage/Path rw,vers=3.1.1,cache=strict,username=user,uid=1000,forceuid,gid=0,noforcegid,addr=127.0.0.1,file_mode=0755,dir_mode=0755,soft,nounix,serverino,mapposix,echo_interval=60,actimeo=1", |
| mount: &MountInfo{ |
| MountId: 454, |
| ParentId: 29, |
| MajorMinorVer: "0:87", |
| Root: "/", |
| MountPoint: "/with/a-hyphen", |
| Options: map[string]string{"rw": "", "relatime": ""}, |
| OptionalFields: map[string]string{"shared": "255"}, |
| FSType: "cifs", |
| Source: "//remote-storage/Path", |
| SuperOptions: map[string]string{"rw": "", "vers": "3.1.1", "cache": "strict", "username": "user", "uid": "1000", "forceuid": "", "gid": "0", "noforcegid": "", "addr": "127.0.0.1", "file_mode": "0755", "dir_mode": "0755", "soft": "", "nounix": "", "serverino": "", "mapposix": "", "echo_interval": "60", "actimeo": "1"}, |
| }, |
| invalid: false, |
| }, |
| } |
| |
| for i, test := range tests { |
| t.Logf("[%02d] test %q", i, test.name) |
| |
| mount, err := parseMountInfoString(test.s) |
| |
| if test.invalid && err == nil { |
| t.Error("expected an error, but none occurred") |
| } |
| if !test.invalid && err != nil { |
| t.Errorf("unexpected error: %v", err) |
| } |
| |
| if want, have := test.mount, mount; !reflect.DeepEqual(want, have) { |
| t.Errorf("mounts:\nwant:\n%+v\nhave:\n%+v", want, have) |
| } |
| } |
| } |