github.com/Heebron/moby@v0.0.0-20221111184709-6eab4f55faf7/pkg/archive/changes_posix_test.go (about)

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