github.com/rentongzhang/docker@v1.8.2-rc1/pkg/archive/changes_posix_test.go (about) 1 package archive 2 3 import ( 4 "archive/tar" 5 "fmt" 6 "io" 7 "io/ioutil" 8 "os" 9 "path" 10 "sort" 11 "testing" 12 ) 13 14 func TestHardLinkOrder(t *testing.T) { 15 names := []string{"file1.txt", "file2.txt", "file3.txt"} 16 msg := []byte("Hey y'all") 17 18 // Create dir 19 src, err := ioutil.TempDir("", "docker-hardlink-test-src-") 20 if err != nil { 21 t.Fatal(err) 22 } 23 //defer os.RemoveAll(src) 24 for _, name := range names { 25 func() { 26 fh, err := os.Create(path.Join(src, name)) 27 if err != nil { 28 t.Fatal(err) 29 } 30 defer fh.Close() 31 if _, err = fh.Write(msg); err != nil { 32 t.Fatal(err) 33 } 34 }() 35 } 36 // Create dest, with changes that includes hardlinks 37 dest, err := ioutil.TempDir("", "docker-hardlink-test-dest-") 38 if err != nil { 39 t.Fatal(err) 40 } 41 os.RemoveAll(dest) // we just want the name, at first 42 if err := copyDir(src, dest); err != nil { 43 t.Fatal(err) 44 } 45 defer os.RemoveAll(dest) 46 for _, name := range names { 47 for i := 0; i < 5; i++ { 48 if err := os.Link(path.Join(dest, name), path.Join(dest, fmt.Sprintf("%s.link%d", name, i))); err != nil { 49 t.Fatal(err) 50 } 51 } 52 } 53 54 // get changes 55 changes, err := ChangesDirs(dest, src) 56 if err != nil { 57 t.Fatal(err) 58 } 59 60 // sort 61 sort.Sort(changesByPath(changes)) 62 63 // ExportChanges 64 ar, err := ExportChanges(dest, changes) 65 if err != nil { 66 t.Fatal(err) 67 } 68 hdrs, err := walkHeaders(ar) 69 if err != nil { 70 t.Fatal(err) 71 } 72 73 // reverse sort 74 sort.Sort(sort.Reverse(changesByPath(changes))) 75 // ExportChanges 76 arRev, err := ExportChanges(dest, changes) 77 if err != nil { 78 t.Fatal(err) 79 } 80 hdrsRev, err := walkHeaders(arRev) 81 if err != nil { 82 t.Fatal(err) 83 } 84 85 // line up the two sets 86 sort.Sort(tarHeaders(hdrs)) 87 sort.Sort(tarHeaders(hdrsRev)) 88 89 // compare Size and LinkName 90 for i := range hdrs { 91 if hdrs[i].Name != hdrsRev[i].Name { 92 t.Errorf("headers - expected name %q; but got %q", hdrs[i].Name, hdrsRev[i].Name) 93 } 94 if hdrs[i].Size != hdrsRev[i].Size { 95 t.Errorf("headers - %q expected size %d; but got %d", hdrs[i].Name, hdrs[i].Size, hdrsRev[i].Size) 96 } 97 if hdrs[i].Typeflag != hdrsRev[i].Typeflag { 98 t.Errorf("headers - %q expected type %d; but got %d", hdrs[i].Name, hdrs[i].Typeflag, hdrsRev[i].Typeflag) 99 } 100 if hdrs[i].Linkname != hdrsRev[i].Linkname { 101 t.Errorf("headers - %q expected linkname %q; but got %q", hdrs[i].Name, hdrs[i].Linkname, hdrsRev[i].Linkname) 102 } 103 } 104 105 } 106 107 type tarHeaders []tar.Header 108 109 func (th tarHeaders) Len() int { return len(th) } 110 func (th tarHeaders) Swap(i, j int) { th[j], th[i] = th[i], th[j] } 111 func (th tarHeaders) Less(i, j int) bool { return th[i].Name < th[j].Name } 112 113 func walkHeaders(r io.Reader) ([]tar.Header, error) { 114 t := tar.NewReader(r) 115 headers := []tar.Header{} 116 for { 117 hdr, err := t.Next() 118 if err != nil { 119 if err == io.EOF { 120 break 121 } 122 return headers, err 123 } 124 headers = append(headers, *hdr) 125 } 126 return headers, nil 127 }