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