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