changes_posix_test.go 2.9 KB

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