github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/cli/opts/mount_test.go (about) 1 package opts 2 3 import ( 4 "os" 5 "testing" 6 7 mounttypes "github.com/docker/docker/api/types/mount" 8 "gotest.tools/v3/assert" 9 is "gotest.tools/v3/assert/cmp" 10 ) 11 12 func TestMountOptString(t *testing.T) { 13 mount := MountOpt{ 14 values: []mounttypes.Mount{ 15 { 16 Type: mounttypes.TypeBind, 17 Source: "/home/path", 18 Target: "/target", 19 }, 20 { 21 Type: mounttypes.TypeVolume, 22 Source: "foo", 23 Target: "/target/foo", 24 }, 25 }, 26 } 27 expected := "bind /home/path /target, volume foo /target/foo" 28 assert.Check(t, is.Equal(expected, mount.String())) 29 } 30 31 func TestMountOptSetBindNoErrorBind(t *testing.T) { 32 for _, testcase := range []string{ 33 // tests several aliases that should have same result. 34 "type=bind,target=/target,source=/source", 35 "type=bind,src=/source,dst=/target", 36 "type=bind,source=/source,dst=/target", 37 "type=bind,src=/source,target=/target", 38 } { 39 var mount MountOpt 40 41 assert.NilError(t, mount.Set(testcase)) 42 43 mounts := mount.Value() 44 assert.Assert(t, is.Len(mounts, 1)) 45 assert.Check(t, is.DeepEqual(mounttypes.Mount{ 46 Type: mounttypes.TypeBind, 47 Source: "/source", 48 Target: "/target", 49 }, mounts[0])) 50 } 51 } 52 53 func TestMountOptSetVolumeNoError(t *testing.T) { 54 for _, testcase := range []string{ 55 // tests several aliases that should have same result. 56 "type=volume,target=/target,source=/source", 57 "type=volume,src=/source,dst=/target", 58 "type=volume,source=/source,dst=/target", 59 "type=volume,src=/source,target=/target", 60 } { 61 var mount MountOpt 62 63 assert.NilError(t, mount.Set(testcase)) 64 65 mounts := mount.Value() 66 assert.Assert(t, is.Len(mounts, 1)) 67 assert.Check(t, is.DeepEqual(mounttypes.Mount{ 68 Type: mounttypes.TypeVolume, 69 Source: "/source", 70 Target: "/target", 71 }, mounts[0])) 72 } 73 } 74 75 // TestMountOptDefaultType ensures that a mount without the type defaults to a 76 // volume mount. 77 func TestMountOptDefaultType(t *testing.T) { 78 var mount MountOpt 79 assert.NilError(t, mount.Set("target=/target,source=/foo")) 80 assert.Check(t, is.Equal(mounttypes.TypeVolume, mount.values[0].Type)) 81 } 82 83 func TestMountOptSetErrorNoTarget(t *testing.T) { 84 var mount MountOpt 85 assert.Error(t, mount.Set("type=volume,source=/foo"), "target is required") 86 } 87 88 func TestMountOptSetErrorInvalidKey(t *testing.T) { 89 var mount MountOpt 90 assert.Error(t, mount.Set("type=volume,bogus=foo"), "unexpected key 'bogus' in 'bogus=foo'") 91 } 92 93 func TestMountOptSetErrorInvalidField(t *testing.T) { 94 var mount MountOpt 95 assert.Error(t, mount.Set("type=volume,bogus"), "invalid field 'bogus' must be a key=value pair") 96 } 97 98 func TestMountOptSetErrorInvalidReadOnly(t *testing.T) { 99 var mount MountOpt 100 assert.Error(t, mount.Set("type=volume,readonly=no"), "invalid value for readonly: no") 101 assert.Error(t, mount.Set("type=volume,readonly=invalid"), "invalid value for readonly: invalid") 102 } 103 104 func TestMountOptDefaultEnableReadOnly(t *testing.T) { 105 var m MountOpt 106 assert.NilError(t, m.Set("type=bind,target=/foo,source=/foo")) 107 assert.Check(t, !m.values[0].ReadOnly) 108 109 m = MountOpt{} 110 assert.NilError(t, m.Set("type=bind,target=/foo,source=/foo,readonly")) 111 assert.Check(t, m.values[0].ReadOnly) 112 113 m = MountOpt{} 114 assert.NilError(t, m.Set("type=bind,target=/foo,source=/foo,readonly=1")) 115 assert.Check(t, m.values[0].ReadOnly) 116 117 m = MountOpt{} 118 assert.NilError(t, m.Set("type=bind,target=/foo,source=/foo,readonly=true")) 119 assert.Check(t, m.values[0].ReadOnly) 120 121 m = MountOpt{} 122 assert.NilError(t, m.Set("type=bind,target=/foo,source=/foo,readonly=0")) 123 assert.Check(t, !m.values[0].ReadOnly) 124 } 125 126 func TestMountOptVolumeNoCopy(t *testing.T) { 127 var m MountOpt 128 assert.NilError(t, m.Set("type=volume,target=/foo,volume-nocopy")) 129 assert.Check(t, is.Equal("", m.values[0].Source)) 130 131 m = MountOpt{} 132 assert.NilError(t, m.Set("type=volume,target=/foo,source=foo")) 133 assert.Check(t, m.values[0].VolumeOptions == nil) 134 135 m = MountOpt{} 136 assert.NilError(t, m.Set("type=volume,target=/foo,source=foo,volume-nocopy=true")) 137 assert.Check(t, m.values[0].VolumeOptions != nil) 138 assert.Check(t, m.values[0].VolumeOptions.NoCopy) 139 140 m = MountOpt{} 141 assert.NilError(t, m.Set("type=volume,target=/foo,source=foo,volume-nocopy")) 142 assert.Check(t, m.values[0].VolumeOptions != nil) 143 assert.Check(t, m.values[0].VolumeOptions.NoCopy) 144 145 m = MountOpt{} 146 assert.NilError(t, m.Set("type=volume,target=/foo,source=foo,volume-nocopy=1")) 147 assert.Check(t, m.values[0].VolumeOptions != nil) 148 assert.Check(t, m.values[0].VolumeOptions.NoCopy) 149 } 150 151 func TestMountOptTypeConflict(t *testing.T) { 152 var m MountOpt 153 assert.ErrorContains(t, m.Set("type=bind,target=/foo,source=/foo,volume-nocopy=true"), "cannot mix") 154 assert.ErrorContains(t, m.Set("type=volume,target=/foo,source=/foo,bind-propagation=rprivate"), "cannot mix") 155 } 156 157 func TestMountOptSetTmpfsNoError(t *testing.T) { 158 for _, testcase := range []string{ 159 // tests several aliases that should have same result. 160 "type=tmpfs,target=/target,tmpfs-size=1m,tmpfs-mode=0700", 161 "type=tmpfs,target=/target,tmpfs-size=1MB,tmpfs-mode=700", 162 } { 163 var mount MountOpt 164 165 assert.NilError(t, mount.Set(testcase)) 166 167 mounts := mount.Value() 168 assert.Assert(t, is.Len(mounts, 1)) 169 assert.Check(t, is.DeepEqual(mounttypes.Mount{ 170 Type: mounttypes.TypeTmpfs, 171 Target: "/target", 172 TmpfsOptions: &mounttypes.TmpfsOptions{ 173 SizeBytes: 1024 * 1024, // not 1000 * 1000 174 Mode: os.FileMode(0700), 175 }, 176 }, mounts[0])) 177 } 178 } 179 180 func TestMountOptSetTmpfsError(t *testing.T) { 181 var m MountOpt 182 assert.ErrorContains(t, m.Set("type=tmpfs,target=/foo,tmpfs-size=foo"), "invalid value for tmpfs-size") 183 assert.ErrorContains(t, m.Set("type=tmpfs,target=/foo,tmpfs-mode=foo"), "invalid value for tmpfs-mode") 184 assert.ErrorContains(t, m.Set("type=tmpfs"), "target is required") 185 }