Tizen_4.0 base
[platform/upstream/docker-engine.git] / volume / local / local_test.go
1 package local
2
3 import (
4         "io/ioutil"
5         "os"
6         "path/filepath"
7         "reflect"
8         "runtime"
9         "strings"
10         "testing"
11
12         "github.com/docker/docker/pkg/idtools"
13         "github.com/docker/docker/pkg/mount"
14 )
15
16 func TestGetAddress(t *testing.T) {
17         cases := map[string]string{
18                 "addr=11.11.11.1":   "11.11.11.1",
19                 " ":                 "",
20                 "addr=":             "",
21                 "addr=2001:db8::68": "2001:db8::68",
22         }
23         for name, success := range cases {
24                 v := getAddress(name)
25                 if v != success {
26                         t.Errorf("Test case failed for %s actual: %s expected : %s", name, v, success)
27                 }
28         }
29
30 }
31
32 func TestRemove(t *testing.T) {
33         // TODO Windows: Investigate why this test fails on Windows under CI
34         //               but passes locally.
35         if runtime.GOOS == "windows" {
36                 t.Skip("Test failing on Windows CI")
37         }
38         rootDir, err := ioutil.TempDir("", "local-volume-test")
39         if err != nil {
40                 t.Fatal(err)
41         }
42         defer os.RemoveAll(rootDir)
43
44         r, err := New(rootDir, idtools.IDPair{UID: 0, GID: 0})
45         if err != nil {
46                 t.Fatal(err)
47         }
48
49         vol, err := r.Create("testing", nil)
50         if err != nil {
51                 t.Fatal(err)
52         }
53
54         if err := r.Remove(vol); err != nil {
55                 t.Fatal(err)
56         }
57
58         vol, err = r.Create("testing2", nil)
59         if err != nil {
60                 t.Fatal(err)
61         }
62         if err := os.RemoveAll(vol.Path()); err != nil {
63                 t.Fatal(err)
64         }
65
66         if err := r.Remove(vol); err != nil {
67                 t.Fatal(err)
68         }
69
70         if _, err := os.Stat(vol.Path()); err != nil && !os.IsNotExist(err) {
71                 t.Fatal("volume dir not removed")
72         }
73
74         if l, _ := r.List(); len(l) != 0 {
75                 t.Fatal("expected there to be no volumes")
76         }
77 }
78
79 func TestInitializeWithVolumes(t *testing.T) {
80         rootDir, err := ioutil.TempDir("", "local-volume-test")
81         if err != nil {
82                 t.Fatal(err)
83         }
84         defer os.RemoveAll(rootDir)
85
86         r, err := New(rootDir, idtools.IDPair{UID: 0, GID: 0})
87         if err != nil {
88                 t.Fatal(err)
89         }
90
91         vol, err := r.Create("testing", nil)
92         if err != nil {
93                 t.Fatal(err)
94         }
95
96         r, err = New(rootDir, idtools.IDPair{UID: 0, GID: 0})
97         if err != nil {
98                 t.Fatal(err)
99         }
100
101         v, err := r.Get(vol.Name())
102         if err != nil {
103                 t.Fatal(err)
104         }
105
106         if v.Path() != vol.Path() {
107                 t.Fatal("expected to re-initialize root with existing volumes")
108         }
109 }
110
111 func TestCreate(t *testing.T) {
112         rootDir, err := ioutil.TempDir("", "local-volume-test")
113         if err != nil {
114                 t.Fatal(err)
115         }
116         defer os.RemoveAll(rootDir)
117
118         r, err := New(rootDir, idtools.IDPair{UID: 0, GID: 0})
119         if err != nil {
120                 t.Fatal(err)
121         }
122
123         cases := map[string]bool{
124                 "name":                  true,
125                 "name-with-dash":        true,
126                 "name_with_underscore":  true,
127                 "name/with/slash":       false,
128                 "name/with/../../slash": false,
129                 "./name":                false,
130                 "../name":               false,
131                 "./":                    false,
132                 "../":                   false,
133                 "~":                     false,
134                 ".":                     false,
135                 "..":                    false,
136                 "...":                   false,
137         }
138
139         for name, success := range cases {
140                 v, err := r.Create(name, nil)
141                 if success {
142                         if err != nil {
143                                 t.Fatal(err)
144                         }
145                         if v.Name() != name {
146                                 t.Fatalf("Expected volume with name %s, got %s", name, v.Name())
147                         }
148                 } else {
149                         if err == nil {
150                                 t.Fatalf("Expected error creating volume with name %s, got nil", name)
151                         }
152                 }
153         }
154
155         r, err = New(rootDir, idtools.IDPair{UID: 0, GID: 0})
156         if err != nil {
157                 t.Fatal(err)
158         }
159 }
160
161 func TestValidateName(t *testing.T) {
162         r := &Root{}
163         names := map[string]bool{
164                 "x":           false,
165                 "/testvol":    false,
166                 "thing.d":     true,
167                 "hello-world": true,
168                 "./hello":     false,
169                 ".hello":      false,
170         }
171
172         for vol, expected := range names {
173                 err := r.validateName(vol)
174                 if expected && err != nil {
175                         t.Fatalf("expected %s to be valid got %v", vol, err)
176                 }
177                 if !expected && err == nil {
178                         t.Fatalf("expected %s to be invalid", vol)
179                 }
180         }
181 }
182
183 func TestCreateWithOpts(t *testing.T) {
184         if runtime.GOOS == "windows" || runtime.GOOS == "solaris" {
185                 t.Skip()
186         }
187         rootDir, err := ioutil.TempDir("", "local-volume-test")
188         if err != nil {
189                 t.Fatal(err)
190         }
191         defer os.RemoveAll(rootDir)
192
193         r, err := New(rootDir, idtools.IDPair{UID: 0, GID: 0})
194         if err != nil {
195                 t.Fatal(err)
196         }
197
198         if _, err := r.Create("test", map[string]string{"invalidopt": "notsupported"}); err == nil {
199                 t.Fatal("expected invalid opt to cause error")
200         }
201
202         vol, err := r.Create("test", map[string]string{"device": "tmpfs", "type": "tmpfs", "o": "size=1m,uid=1000"})
203         if err != nil {
204                 t.Fatal(err)
205         }
206         v := vol.(*localVolume)
207
208         dir, err := v.Mount("1234")
209         if err != nil {
210                 t.Fatal(err)
211         }
212         defer func() {
213                 if err := v.Unmount("1234"); err != nil {
214                         t.Fatal(err)
215                 }
216         }()
217
218         mountInfos, err := mount.GetMounts()
219         if err != nil {
220                 t.Fatal(err)
221         }
222
223         var found bool
224         for _, info := range mountInfos {
225                 if info.Mountpoint == dir {
226                         found = true
227                         if info.Fstype != "tmpfs" {
228                                 t.Fatalf("expected tmpfs mount, got %q", info.Fstype)
229                         }
230                         if info.Source != "tmpfs" {
231                                 t.Fatalf("expected tmpfs mount, got %q", info.Source)
232                         }
233                         if !strings.Contains(info.VfsOpts, "uid=1000") {
234                                 t.Fatalf("expected mount info to have uid=1000: %q", info.VfsOpts)
235                         }
236                         if !strings.Contains(info.VfsOpts, "size=1024k") {
237                                 t.Fatalf("expected mount info to have size=1024k: %q", info.VfsOpts)
238                         }
239                         break
240                 }
241         }
242
243         if !found {
244                 t.Fatal("mount not found")
245         }
246
247         if v.active.count != 1 {
248                 t.Fatalf("Expected active mount count to be 1, got %d", v.active.count)
249         }
250
251         // test double mount
252         if _, err := v.Mount("1234"); err != nil {
253                 t.Fatal(err)
254         }
255         if v.active.count != 2 {
256                 t.Fatalf("Expected active mount count to be 2, got %d", v.active.count)
257         }
258
259         if err := v.Unmount("1234"); err != nil {
260                 t.Fatal(err)
261         }
262         if v.active.count != 1 {
263                 t.Fatalf("Expected active mount count to be 1, got %d", v.active.count)
264         }
265
266         mounted, err := mount.Mounted(v.path)
267         if err != nil {
268                 t.Fatal(err)
269         }
270         if !mounted {
271                 t.Fatal("expected mount to still be active")
272         }
273
274         r, err = New(rootDir, idtools.IDPair{UID: 0, GID: 0})
275         if err != nil {
276                 t.Fatal(err)
277         }
278
279         v2, exists := r.volumes["test"]
280         if !exists {
281                 t.Fatal("missing volume on restart")
282         }
283
284         if !reflect.DeepEqual(v.opts, v2.opts) {
285                 t.Fatal("missing volume options on restart")
286         }
287 }
288
289 func TestRealodNoOpts(t *testing.T) {
290         rootDir, err := ioutil.TempDir("", "volume-test-reload-no-opts")
291         if err != nil {
292                 t.Fatal(err)
293         }
294         defer os.RemoveAll(rootDir)
295
296         r, err := New(rootDir, idtools.IDPair{UID: 0, GID: 0})
297         if err != nil {
298                 t.Fatal(err)
299         }
300
301         if _, err := r.Create("test1", nil); err != nil {
302                 t.Fatal(err)
303         }
304         if _, err := r.Create("test2", nil); err != nil {
305                 t.Fatal(err)
306         }
307         // make sure a file with `null` (.e.g. empty opts map from older daemon) is ok
308         if err := ioutil.WriteFile(filepath.Join(rootDir, "test2"), []byte("null"), 600); err != nil {
309                 t.Fatal(err)
310         }
311
312         if _, err := r.Create("test3", nil); err != nil {
313                 t.Fatal(err)
314         }
315         // make sure an empty opts file doesn't break us too
316         if err := ioutil.WriteFile(filepath.Join(rootDir, "test3"), nil, 600); err != nil {
317                 t.Fatal(err)
318         }
319
320         if _, err := r.Create("test4", map[string]string{}); err != nil {
321                 t.Fatal(err)
322         }
323
324         r, err = New(rootDir, idtools.IDPair{UID: 0, GID: 0})
325         if err != nil {
326                 t.Fatal(err)
327         }
328
329         for _, name := range []string{"test1", "test2", "test3", "test4"} {
330                 v, err := r.Get(name)
331                 if err != nil {
332                         t.Fatal(err)
333                 }
334                 lv, ok := v.(*localVolume)
335                 if !ok {
336                         t.Fatalf("expected *localVolume got: %v", reflect.TypeOf(v))
337                 }
338                 if lv.opts != nil {
339                         t.Fatalf("expected opts to be nil, got: %v", lv.opts)
340                 }
341                 if _, err := lv.Mount("1234"); err != nil {
342                         t.Fatal(err)
343                 }
344         }
345 }