Tizen_4.0 base
[platform/upstream/docker-engine.git] / daemon / graphdriver / aufs / aufs_test.go
1 // +build linux
2
3 package aufs
4
5 import (
6         "crypto/sha256"
7         "encoding/hex"
8         "fmt"
9         "io/ioutil"
10         "os"
11         "path"
12         "sync"
13         "testing"
14
15         "github.com/docker/docker/daemon/graphdriver"
16         "github.com/docker/docker/pkg/archive"
17         "github.com/docker/docker/pkg/reexec"
18         "github.com/docker/docker/pkg/stringid"
19 )
20
21 var (
22         tmpOuter = path.Join(os.TempDir(), "aufs-tests")
23         tmp      = path.Join(tmpOuter, "aufs")
24 )
25
26 func init() {
27         reexec.Init()
28 }
29
30 func testInit(dir string, t testing.TB) graphdriver.Driver {
31         d, err := Init(dir, nil, nil, nil)
32         if err != nil {
33                 if err == graphdriver.ErrNotSupported {
34                         t.Skip(err)
35                 } else {
36                         t.Fatal(err)
37                 }
38         }
39         return d
40 }
41
42 func newDriver(t testing.TB) *Driver {
43         if err := os.MkdirAll(tmp, 0755); err != nil {
44                 t.Fatal(err)
45         }
46
47         d := testInit(tmp, t)
48         return d.(*Driver)
49 }
50
51 func TestNewDriver(t *testing.T) {
52         if err := os.MkdirAll(tmp, 0755); err != nil {
53                 t.Fatal(err)
54         }
55
56         d := testInit(tmp, t)
57         defer os.RemoveAll(tmp)
58         if d == nil {
59                 t.Fatal("Driver should not be nil")
60         }
61 }
62
63 func TestAufsString(t *testing.T) {
64         d := newDriver(t)
65         defer os.RemoveAll(tmp)
66
67         if d.String() != "aufs" {
68                 t.Fatalf("Expected aufs got %s", d.String())
69         }
70 }
71
72 func TestCreateDirStructure(t *testing.T) {
73         newDriver(t)
74         defer os.RemoveAll(tmp)
75
76         paths := []string{
77                 "mnt",
78                 "layers",
79                 "diff",
80         }
81
82         for _, p := range paths {
83                 if _, err := os.Stat(path.Join(tmp, p)); err != nil {
84                         t.Fatal(err)
85                 }
86         }
87 }
88
89 // We should be able to create two drivers with the same dir structure
90 func TestNewDriverFromExistingDir(t *testing.T) {
91         if err := os.MkdirAll(tmp, 0755); err != nil {
92                 t.Fatal(err)
93         }
94
95         testInit(tmp, t)
96         testInit(tmp, t)
97         os.RemoveAll(tmp)
98 }
99
100 func TestCreateNewDir(t *testing.T) {
101         d := newDriver(t)
102         defer os.RemoveAll(tmp)
103
104         if err := d.Create("1", "", nil); err != nil {
105                 t.Fatal(err)
106         }
107 }
108
109 func TestCreateNewDirStructure(t *testing.T) {
110         d := newDriver(t)
111         defer os.RemoveAll(tmp)
112
113         if err := d.Create("1", "", nil); err != nil {
114                 t.Fatal(err)
115         }
116
117         paths := []string{
118                 "mnt",
119                 "diff",
120                 "layers",
121         }
122
123         for _, p := range paths {
124                 if _, err := os.Stat(path.Join(tmp, p, "1")); err != nil {
125                         t.Fatal(err)
126                 }
127         }
128 }
129
130 func TestRemoveImage(t *testing.T) {
131         d := newDriver(t)
132         defer os.RemoveAll(tmp)
133
134         if err := d.Create("1", "", nil); err != nil {
135                 t.Fatal(err)
136         }
137
138         if err := d.Remove("1"); err != nil {
139                 t.Fatal(err)
140         }
141
142         paths := []string{
143                 "mnt",
144                 "diff",
145                 "layers",
146         }
147
148         for _, p := range paths {
149                 if _, err := os.Stat(path.Join(tmp, p, "1")); err == nil {
150                         t.Fatalf("Error should not be nil because dirs with id 1 should be delted: %s", p)
151                 }
152         }
153 }
154
155 func TestGetWithoutParent(t *testing.T) {
156         d := newDriver(t)
157         defer os.RemoveAll(tmp)
158
159         if err := d.Create("1", "", nil); err != nil {
160                 t.Fatal(err)
161         }
162
163         diffPath, err := d.Get("1", "")
164         if err != nil {
165                 t.Fatal(err)
166         }
167         expected := path.Join(tmp, "diff", "1")
168         if diffPath != expected {
169                 t.Fatalf("Expected path %s got %s", expected, diffPath)
170         }
171 }
172
173 func TestCleanupWithNoDirs(t *testing.T) {
174         d := newDriver(t)
175         defer os.RemoveAll(tmp)
176
177         if err := d.Cleanup(); err != nil {
178                 t.Fatal(err)
179         }
180 }
181
182 func TestCleanupWithDir(t *testing.T) {
183         d := newDriver(t)
184         defer os.RemoveAll(tmp)
185
186         if err := d.Create("1", "", nil); err != nil {
187                 t.Fatal(err)
188         }
189
190         if err := d.Cleanup(); err != nil {
191                 t.Fatal(err)
192         }
193 }
194
195 func TestMountedFalseResponse(t *testing.T) {
196         d := newDriver(t)
197         defer os.RemoveAll(tmp)
198
199         if err := d.Create("1", "", nil); err != nil {
200                 t.Fatal(err)
201         }
202
203         response, err := d.mounted(d.getDiffPath("1"))
204         if err != nil {
205                 t.Fatal(err)
206         }
207
208         if response != false {
209                 t.Fatal("Response if dir id 1 is mounted should be false")
210         }
211 }
212
213 func TestMountedTrueResponse(t *testing.T) {
214         d := newDriver(t)
215         defer os.RemoveAll(tmp)
216         defer d.Cleanup()
217
218         if err := d.Create("1", "", nil); err != nil {
219                 t.Fatal(err)
220         }
221         if err := d.Create("2", "1", nil); err != nil {
222                 t.Fatal(err)
223         }
224
225         _, err := d.Get("2", "")
226         if err != nil {
227                 t.Fatal(err)
228         }
229
230         response, err := d.mounted(d.pathCache["2"])
231         if err != nil {
232                 t.Fatal(err)
233         }
234
235         if response != true {
236                 t.Fatal("Response if dir id 2 is mounted should be true")
237         }
238 }
239
240 func TestMountWithParent(t *testing.T) {
241         d := newDriver(t)
242         defer os.RemoveAll(tmp)
243
244         if err := d.Create("1", "", nil); err != nil {
245                 t.Fatal(err)
246         }
247         if err := d.Create("2", "1", nil); err != nil {
248                 t.Fatal(err)
249         }
250
251         defer func() {
252                 if err := d.Cleanup(); err != nil {
253                         t.Fatal(err)
254                 }
255         }()
256
257         mntPath, err := d.Get("2", "")
258         if err != nil {
259                 t.Fatal(err)
260         }
261         if mntPath == "" {
262                 t.Fatal("mntPath should not be empty string")
263         }
264
265         expected := path.Join(tmp, "mnt", "2")
266         if mntPath != expected {
267                 t.Fatalf("Expected %s got %s", expected, mntPath)
268         }
269 }
270
271 func TestRemoveMountedDir(t *testing.T) {
272         d := newDriver(t)
273         defer os.RemoveAll(tmp)
274
275         if err := d.Create("1", "", nil); err != nil {
276                 t.Fatal(err)
277         }
278         if err := d.Create("2", "1", nil); err != nil {
279                 t.Fatal(err)
280         }
281
282         defer func() {
283                 if err := d.Cleanup(); err != nil {
284                         t.Fatal(err)
285                 }
286         }()
287
288         mntPath, err := d.Get("2", "")
289         if err != nil {
290                 t.Fatal(err)
291         }
292         if mntPath == "" {
293                 t.Fatal("mntPath should not be empty string")
294         }
295
296         mounted, err := d.mounted(d.pathCache["2"])
297         if err != nil {
298                 t.Fatal(err)
299         }
300
301         if !mounted {
302                 t.Fatal("Dir id 2 should be mounted")
303         }
304
305         if err := d.Remove("2"); err != nil {
306                 t.Fatal(err)
307         }
308 }
309
310 func TestCreateWithInvalidParent(t *testing.T) {
311         d := newDriver(t)
312         defer os.RemoveAll(tmp)
313
314         if err := d.Create("1", "docker", nil); err == nil {
315                 t.Fatal("Error should not be nil with parent does not exist")
316         }
317 }
318
319 func TestGetDiff(t *testing.T) {
320         d := newDriver(t)
321         defer os.RemoveAll(tmp)
322
323         if err := d.CreateReadWrite("1", "", nil); err != nil {
324                 t.Fatal(err)
325         }
326
327         diffPath, err := d.Get("1", "")
328         if err != nil {
329                 t.Fatal(err)
330         }
331
332         // Add a file to the diff path with a fixed size
333         size := int64(1024)
334
335         f, err := os.Create(path.Join(diffPath, "test_file"))
336         if err != nil {
337                 t.Fatal(err)
338         }
339         if err := f.Truncate(size); err != nil {
340                 t.Fatal(err)
341         }
342         f.Close()
343
344         a, err := d.Diff("1", "")
345         if err != nil {
346                 t.Fatal(err)
347         }
348         if a == nil {
349                 t.Fatal("Archive should not be nil")
350         }
351 }
352
353 func TestChanges(t *testing.T) {
354         d := newDriver(t)
355         defer os.RemoveAll(tmp)
356
357         if err := d.Create("1", "", nil); err != nil {
358                 t.Fatal(err)
359         }
360
361         if err := d.CreateReadWrite("2", "1", nil); err != nil {
362                 t.Fatal(err)
363         }
364
365         defer func() {
366                 if err := d.Cleanup(); err != nil {
367                         t.Fatal(err)
368                 }
369         }()
370
371         mntPoint, err := d.Get("2", "")
372         if err != nil {
373                 t.Fatal(err)
374         }
375
376         // Create a file to save in the mountpoint
377         f, err := os.Create(path.Join(mntPoint, "test.txt"))
378         if err != nil {
379                 t.Fatal(err)
380         }
381
382         if _, err := f.WriteString("testline"); err != nil {
383                 t.Fatal(err)
384         }
385         if err := f.Close(); err != nil {
386                 t.Fatal(err)
387         }
388
389         changes, err := d.Changes("2", "")
390         if err != nil {
391                 t.Fatal(err)
392         }
393         if len(changes) != 1 {
394                 t.Fatalf("Dir 2 should have one change from parent got %d", len(changes))
395         }
396         change := changes[0]
397
398         expectedPath := "/test.txt"
399         if change.Path != expectedPath {
400                 t.Fatalf("Expected path %s got %s", expectedPath, change.Path)
401         }
402
403         if change.Kind != archive.ChangeAdd {
404                 t.Fatalf("Change kind should be ChangeAdd got %s", change.Kind)
405         }
406
407         if err := d.CreateReadWrite("3", "2", nil); err != nil {
408                 t.Fatal(err)
409         }
410         mntPoint, err = d.Get("3", "")
411         if err != nil {
412                 t.Fatal(err)
413         }
414
415         // Create a file to save in the mountpoint
416         f, err = os.Create(path.Join(mntPoint, "test2.txt"))
417         if err != nil {
418                 t.Fatal(err)
419         }
420
421         if _, err := f.WriteString("testline"); err != nil {
422                 t.Fatal(err)
423         }
424         if err := f.Close(); err != nil {
425                 t.Fatal(err)
426         }
427
428         changes, err = d.Changes("3", "2")
429         if err != nil {
430                 t.Fatal(err)
431         }
432
433         if len(changes) != 1 {
434                 t.Fatalf("Dir 2 should have one change from parent got %d", len(changes))
435         }
436         change = changes[0]
437
438         expectedPath = "/test2.txt"
439         if change.Path != expectedPath {
440                 t.Fatalf("Expected path %s got %s", expectedPath, change.Path)
441         }
442
443         if change.Kind != archive.ChangeAdd {
444                 t.Fatalf("Change kind should be ChangeAdd got %s", change.Kind)
445         }
446 }
447
448 func TestDiffSize(t *testing.T) {
449         d := newDriver(t)
450         defer os.RemoveAll(tmp)
451
452         if err := d.CreateReadWrite("1", "", nil); err != nil {
453                 t.Fatal(err)
454         }
455
456         diffPath, err := d.Get("1", "")
457         if err != nil {
458                 t.Fatal(err)
459         }
460
461         // Add a file to the diff path with a fixed size
462         size := int64(1024)
463
464         f, err := os.Create(path.Join(diffPath, "test_file"))
465         if err != nil {
466                 t.Fatal(err)
467         }
468         if err := f.Truncate(size); err != nil {
469                 t.Fatal(err)
470         }
471         s, err := f.Stat()
472         if err != nil {
473                 t.Fatal(err)
474         }
475         size = s.Size()
476         if err := f.Close(); err != nil {
477                 t.Fatal(err)
478         }
479
480         diffSize, err := d.DiffSize("1", "")
481         if err != nil {
482                 t.Fatal(err)
483         }
484         if diffSize != size {
485                 t.Fatalf("Expected size to be %d got %d", size, diffSize)
486         }
487 }
488
489 func TestChildDiffSize(t *testing.T) {
490         d := newDriver(t)
491         defer os.RemoveAll(tmp)
492         defer d.Cleanup()
493
494         if err := d.CreateReadWrite("1", "", nil); err != nil {
495                 t.Fatal(err)
496         }
497
498         diffPath, err := d.Get("1", "")
499         if err != nil {
500                 t.Fatal(err)
501         }
502
503         // Add a file to the diff path with a fixed size
504         size := int64(1024)
505
506         f, err := os.Create(path.Join(diffPath, "test_file"))
507         if err != nil {
508                 t.Fatal(err)
509         }
510         if err := f.Truncate(size); err != nil {
511                 t.Fatal(err)
512         }
513         s, err := f.Stat()
514         if err != nil {
515                 t.Fatal(err)
516         }
517         size = s.Size()
518         if err := f.Close(); err != nil {
519                 t.Fatal(err)
520         }
521
522         diffSize, err := d.DiffSize("1", "")
523         if err != nil {
524                 t.Fatal(err)
525         }
526         if diffSize != size {
527                 t.Fatalf("Expected size to be %d got %d", size, diffSize)
528         }
529
530         if err := d.Create("2", "1", nil); err != nil {
531                 t.Fatal(err)
532         }
533
534         diffSize, err = d.DiffSize("2", "1")
535         if err != nil {
536                 t.Fatal(err)
537         }
538         // The diff size for the child should be zero
539         if diffSize != 0 {
540                 t.Fatalf("Expected size to be %d got %d", 0, diffSize)
541         }
542 }
543
544 func TestExists(t *testing.T) {
545         d := newDriver(t)
546         defer os.RemoveAll(tmp)
547         defer d.Cleanup()
548
549         if err := d.Create("1", "", nil); err != nil {
550                 t.Fatal(err)
551         }
552
553         if d.Exists("none") {
554                 t.Fatal("id none should not exist in the driver")
555         }
556
557         if !d.Exists("1") {
558                 t.Fatal("id 1 should exist in the driver")
559         }
560 }
561
562 func TestStatus(t *testing.T) {
563         d := newDriver(t)
564         defer os.RemoveAll(tmp)
565         defer d.Cleanup()
566
567         if err := d.Create("1", "", nil); err != nil {
568                 t.Fatal(err)
569         }
570
571         status := d.Status()
572         if status == nil || len(status) == 0 {
573                 t.Fatal("Status should not be nil or empty")
574         }
575         rootDir := status[0]
576         dirs := status[2]
577         if rootDir[0] != "Root Dir" {
578                 t.Fatalf("Expected Root Dir got %s", rootDir[0])
579         }
580         if rootDir[1] != d.rootPath() {
581                 t.Fatalf("Expected %s got %s", d.rootPath(), rootDir[1])
582         }
583         if dirs[0] != "Dirs" {
584                 t.Fatalf("Expected Dirs got %s", dirs[0])
585         }
586         if dirs[1] != "1" {
587                 t.Fatalf("Expected 1 got %s", dirs[1])
588         }
589 }
590
591 func TestApplyDiff(t *testing.T) {
592         d := newDriver(t)
593         defer os.RemoveAll(tmp)
594         defer d.Cleanup()
595
596         if err := d.CreateReadWrite("1", "", nil); err != nil {
597                 t.Fatal(err)
598         }
599
600         diffPath, err := d.Get("1", "")
601         if err != nil {
602                 t.Fatal(err)
603         }
604
605         // Add a file to the diff path with a fixed size
606         size := int64(1024)
607
608         f, err := os.Create(path.Join(diffPath, "test_file"))
609         if err != nil {
610                 t.Fatal(err)
611         }
612         if err := f.Truncate(size); err != nil {
613                 t.Fatal(err)
614         }
615         f.Close()
616
617         diff, err := d.Diff("1", "")
618         if err != nil {
619                 t.Fatal(err)
620         }
621
622         if err := d.Create("2", "", nil); err != nil {
623                 t.Fatal(err)
624         }
625         if err := d.Create("3", "2", nil); err != nil {
626                 t.Fatal(err)
627         }
628
629         if err := d.applyDiff("3", diff); err != nil {
630                 t.Fatal(err)
631         }
632
633         // Ensure that the file is in the mount point for id 3
634
635         mountPoint, err := d.Get("3", "")
636         if err != nil {
637                 t.Fatal(err)
638         }
639         if _, err := os.Stat(path.Join(mountPoint, "test_file")); err != nil {
640                 t.Fatal(err)
641         }
642 }
643
644 func hash(c string) string {
645         h := sha256.New()
646         fmt.Fprint(h, c)
647         return hex.EncodeToString(h.Sum(nil))
648 }
649
650 func testMountMoreThan42Layers(t *testing.T, mountPath string) {
651         if err := os.MkdirAll(mountPath, 0755); err != nil {
652                 t.Fatal(err)
653         }
654
655         defer os.RemoveAll(mountPath)
656         d := testInit(mountPath, t).(*Driver)
657         defer d.Cleanup()
658         var last string
659         var expected int
660
661         for i := 1; i < 127; i++ {
662                 expected++
663                 var (
664                         parent  = fmt.Sprintf("%d", i-1)
665                         current = fmt.Sprintf("%d", i)
666                 )
667
668                 if parent == "0" {
669                         parent = ""
670                 } else {
671                         parent = hash(parent)
672                 }
673                 current = hash(current)
674
675                 if err := d.CreateReadWrite(current, parent, nil); err != nil {
676                         t.Logf("Current layer %d", i)
677                         t.Error(err)
678                 }
679                 point, err := d.Get(current, "")
680                 if err != nil {
681                         t.Logf("Current layer %d", i)
682                         t.Error(err)
683                 }
684                 f, err := os.Create(path.Join(point, current))
685                 if err != nil {
686                         t.Logf("Current layer %d", i)
687                         t.Error(err)
688                 }
689                 f.Close()
690
691                 if i%10 == 0 {
692                         if err := os.Remove(path.Join(point, parent)); err != nil {
693                                 t.Logf("Current layer %d", i)
694                                 t.Error(err)
695                         }
696                         expected--
697                 }
698                 last = current
699         }
700
701         // Perform the actual mount for the top most image
702         point, err := d.Get(last, "")
703         if err != nil {
704                 t.Error(err)
705         }
706         files, err := ioutil.ReadDir(point)
707         if err != nil {
708                 t.Error(err)
709         }
710         if len(files) != expected {
711                 t.Errorf("Expected %d got %d", expected, len(files))
712         }
713 }
714
715 func TestMountMoreThan42Layers(t *testing.T) {
716         os.RemoveAll(tmpOuter)
717         testMountMoreThan42Layers(t, tmp)
718 }
719
720 func TestMountMoreThan42LayersMatchingPathLength(t *testing.T) {
721         defer os.RemoveAll(tmpOuter)
722         zeroes := "0"
723         for {
724                 // This finds a mount path so that when combined into aufs mount options
725                 // 4096 byte boundary would be in between the paths or in permission
726                 // section. For '/tmp' it will use '/tmp/aufs-tests/00000000/aufs'
727                 mountPath := path.Join(tmpOuter, zeroes, "aufs")
728                 pathLength := 77 + len(mountPath)
729
730                 if mod := 4095 % pathLength; mod == 0 || mod > pathLength-2 {
731                         t.Logf("Using path: %s", mountPath)
732                         testMountMoreThan42Layers(t, mountPath)
733                         return
734                 }
735                 zeroes += "0"
736         }
737 }
738
739 func BenchmarkConcurrentAccess(b *testing.B) {
740         b.StopTimer()
741         b.ResetTimer()
742
743         d := newDriver(b)
744         defer os.RemoveAll(tmp)
745         defer d.Cleanup()
746
747         numConcurrent := 256
748         // create a bunch of ids
749         var ids []string
750         for i := 0; i < numConcurrent; i++ {
751                 ids = append(ids, stringid.GenerateNonCryptoID())
752         }
753
754         if err := d.Create(ids[0], "", nil); err != nil {
755                 b.Fatal(err)
756         }
757
758         if err := d.Create(ids[1], ids[0], nil); err != nil {
759                 b.Fatal(err)
760         }
761
762         parent := ids[1]
763         ids = append(ids[2:])
764
765         chErr := make(chan error, numConcurrent)
766         var outerGroup sync.WaitGroup
767         outerGroup.Add(len(ids))
768         b.StartTimer()
769
770         // here's the actual bench
771         for _, id := range ids {
772                 go func(id string) {
773                         defer outerGroup.Done()
774                         if err := d.Create(id, parent, nil); err != nil {
775                                 b.Logf("Create %s failed", id)
776                                 chErr <- err
777                                 return
778                         }
779                         var innerGroup sync.WaitGroup
780                         for i := 0; i < b.N; i++ {
781                                 innerGroup.Add(1)
782                                 go func() {
783                                         d.Get(id, "")
784                                         d.Put(id)
785                                         innerGroup.Done()
786                                 }()
787                         }
788                         innerGroup.Wait()
789                         d.Remove(id)
790                 }(id)
791         }
792
793         outerGroup.Wait()
794         b.StopTimer()
795         close(chErr)
796         for err := range chErr {
797                 if err != nil {
798                         b.Log(err)
799                         b.Fail()
800                 }
801         }
802 }