github.com/toplink-cn/moby@v0.0.0-20240305205811-460b4aebdf81/layer/mount_test.go (about)

     1  package layer // import "github.com/docker/docker/layer"
     2  
     3  import (
     4  	"io"
     5  	"os"
     6  	"path/filepath"
     7  	"runtime"
     8  	"sort"
     9  	"testing"
    10  
    11  	"github.com/containerd/continuity/driver"
    12  	"github.com/docker/docker/pkg/archive"
    13  )
    14  
    15  func TestMountInit(t *testing.T) {
    16  	// TODO Windows: Figure out why this is failing
    17  	if runtime.GOOS == "windows" {
    18  		t.Skip("Failing on Windows")
    19  	}
    20  	ls, _, cleanup := newTestStore(t)
    21  	defer cleanup()
    22  
    23  	basefile := newTestFile("testfile.txt", []byte("base data!"), 0o644)
    24  	initfile := newTestFile("testfile.txt", []byte("init data!"), 0o777)
    25  
    26  	li := initWithFiles(basefile)
    27  	layer, err := createLayer(ls, "", li)
    28  	if err != nil {
    29  		t.Fatal(err)
    30  	}
    31  
    32  	mountInit := func(root string) error {
    33  		return initfile.ApplyFile(root)
    34  	}
    35  
    36  	rwLayerOpts := &CreateRWLayerOpts{
    37  		InitFunc: mountInit,
    38  	}
    39  	m, err := ls.CreateRWLayer("fun-mount", layer.ChainID(), rwLayerOpts)
    40  	if err != nil {
    41  		t.Fatal(err)
    42  	}
    43  
    44  	pathFS, err := m.Mount("")
    45  	if err != nil {
    46  		t.Fatal(err)
    47  	}
    48  
    49  	fi, err := os.Stat(filepath.Join(pathFS, "testfile.txt"))
    50  	if err != nil {
    51  		t.Fatal(err)
    52  	}
    53  
    54  	f, err := os.Open(filepath.Join(pathFS, "testfile.txt"))
    55  	if err != nil {
    56  		t.Fatal(err)
    57  	}
    58  	defer f.Close()
    59  
    60  	b, err := io.ReadAll(f)
    61  	if err != nil {
    62  		t.Fatal(err)
    63  	}
    64  
    65  	if expected := "init data!"; string(b) != expected {
    66  		t.Fatalf("Unexpected test file contents %q, expected %q", string(b), expected)
    67  	}
    68  
    69  	if fi.Mode().Perm() != 0o777 {
    70  		t.Fatalf("Unexpected filemode %o, expecting %o", fi.Mode().Perm(), 0o777)
    71  	}
    72  }
    73  
    74  func TestMountSize(t *testing.T) {
    75  	// TODO Windows: Figure out why this is failing
    76  	if runtime.GOOS == "windows" {
    77  		t.Skip("Failing on Windows")
    78  	}
    79  	ls, _, cleanup := newTestStore(t)
    80  	defer cleanup()
    81  
    82  	content1 := []byte("Base contents")
    83  	content2 := []byte("Mutable contents")
    84  	contentInit := []byte("why am I excluded from the size ☹")
    85  
    86  	li := initWithFiles(newTestFile("file1", content1, 0o644))
    87  	layer, err := createLayer(ls, "", li)
    88  	if err != nil {
    89  		t.Fatal(err)
    90  	}
    91  
    92  	mountInit := func(root string) error {
    93  		return newTestFile("file-init", contentInit, 0o777).ApplyFile(root)
    94  	}
    95  	rwLayerOpts := &CreateRWLayerOpts{
    96  		InitFunc: mountInit,
    97  	}
    98  
    99  	m, err := ls.CreateRWLayer("mount-size", layer.ChainID(), rwLayerOpts)
   100  	if err != nil {
   101  		t.Fatal(err)
   102  	}
   103  
   104  	pathFS, err := m.Mount("")
   105  	if err != nil {
   106  		t.Fatal(err)
   107  	}
   108  
   109  	if err := os.WriteFile(filepath.Join(pathFS, "file2"), content2, 0o755); err != nil {
   110  		t.Fatal(err)
   111  	}
   112  
   113  	mountSize, err := m.Size()
   114  	if err != nil {
   115  		t.Fatal(err)
   116  	}
   117  
   118  	if expected := len(content2); int(mountSize) != expected {
   119  		t.Fatalf("Unexpected mount size %d, expected %d", int(mountSize), expected)
   120  	}
   121  }
   122  
   123  func TestMountChanges(t *testing.T) {
   124  	// TODO Windows: Figure out why this is failing
   125  	if runtime.GOOS == "windows" {
   126  		t.Skip("Failing on Windows")
   127  	}
   128  	ls, _, cleanup := newTestStore(t)
   129  	defer cleanup()
   130  
   131  	basefiles := []FileApplier{
   132  		newTestFile("testfile1.txt", []byte("base data!"), 0o644),
   133  		newTestFile("testfile2.txt", []byte("base data!"), 0o644),
   134  		newTestFile("testfile3.txt", []byte("base data!"), 0o644),
   135  	}
   136  	initfile := newTestFile("testfile1.txt", []byte("init data!"), 0o777)
   137  
   138  	li := initWithFiles(basefiles...)
   139  	layer, err := createLayer(ls, "", li)
   140  	if err != nil {
   141  		t.Fatal(err)
   142  	}
   143  
   144  	mountInit := func(root string) error {
   145  		return initfile.ApplyFile(root)
   146  	}
   147  	rwLayerOpts := &CreateRWLayerOpts{
   148  		InitFunc: mountInit,
   149  	}
   150  
   151  	m, err := ls.CreateRWLayer("mount-changes", layer.ChainID(), rwLayerOpts)
   152  	if err != nil {
   153  		t.Fatal(err)
   154  	}
   155  
   156  	pathFS, err := m.Mount("")
   157  	if err != nil {
   158  		t.Fatal(err)
   159  	}
   160  
   161  	if err := driver.LocalDriver.Lchmod(filepath.Join(pathFS, "testfile1.txt"), 0o755); err != nil {
   162  		t.Fatal(err)
   163  	}
   164  
   165  	if err := os.WriteFile(filepath.Join(pathFS, "testfile1.txt"), []byte("mount data!"), 0o755); err != nil {
   166  		t.Fatal(err)
   167  	}
   168  
   169  	if err := os.Remove(filepath.Join(pathFS, "testfile2.txt")); err != nil {
   170  		t.Fatal(err)
   171  	}
   172  
   173  	if err := driver.LocalDriver.Lchmod(filepath.Join(pathFS, "testfile3.txt"), 0o755); err != nil {
   174  		t.Fatal(err)
   175  	}
   176  
   177  	if err := os.WriteFile(filepath.Join(pathFS, "testfile4.txt"), []byte("mount data!"), 0o644); err != nil {
   178  		t.Fatal(err)
   179  	}
   180  
   181  	changes, err := m.Changes()
   182  	if err != nil {
   183  		t.Fatal(err)
   184  	}
   185  
   186  	if expected := 4; len(changes) != expected {
   187  		t.Fatalf("Wrong number of changes %d, expected %d", len(changes), expected)
   188  	}
   189  
   190  	sortChanges(changes)
   191  
   192  	assertChange(t, changes[0], archive.Change{
   193  		Path: "/testfile1.txt",
   194  		Kind: archive.ChangeModify,
   195  	})
   196  	assertChange(t, changes[1], archive.Change{
   197  		Path: "/testfile2.txt",
   198  		Kind: archive.ChangeDelete,
   199  	})
   200  	assertChange(t, changes[2], archive.Change{
   201  		Path: "/testfile3.txt",
   202  		Kind: archive.ChangeModify,
   203  	})
   204  	assertChange(t, changes[3], archive.Change{
   205  		Path: "/testfile4.txt",
   206  		Kind: archive.ChangeAdd,
   207  	})
   208  }
   209  
   210  func TestMountApply(t *testing.T) {
   211  	// TODO Windows: Figure out why this is failing
   212  	if runtime.GOOS == "windows" {
   213  		t.Skip("Failing on Windows")
   214  	}
   215  	ls, _, cleanup := newTestStore(t)
   216  	defer cleanup()
   217  
   218  	basefile := newTestFile("testfile.txt", []byte("base data!"), 0o644)
   219  	newfile := newTestFile("newfile.txt", []byte("new data!"), 0o755)
   220  
   221  	li := initWithFiles(basefile)
   222  	layer, err := createLayer(ls, "", li)
   223  	if err != nil {
   224  		t.Fatal(err)
   225  	}
   226  
   227  	di := initWithFiles(newfile)
   228  	diffLayer, err := createLayer(ls, "", di)
   229  	if err != nil {
   230  		t.Fatal(err)
   231  	}
   232  
   233  	m, err := ls.CreateRWLayer("fun-mount", layer.ChainID(), nil)
   234  	if err != nil {
   235  		t.Fatal(err)
   236  	}
   237  
   238  	r, err := diffLayer.TarStream()
   239  	if err != nil {
   240  		t.Fatal(err)
   241  	}
   242  
   243  	if _, err := m.ApplyDiff(r); err != nil {
   244  		t.Fatal(err)
   245  	}
   246  
   247  	pathFS, err := m.Mount("")
   248  	if err != nil {
   249  		t.Fatal(err)
   250  	}
   251  
   252  	f, err := os.Open(filepath.Join(pathFS, "newfile.txt"))
   253  	if err != nil {
   254  		t.Fatal(err)
   255  	}
   256  	defer f.Close()
   257  
   258  	b, err := io.ReadAll(f)
   259  	if err != nil {
   260  		t.Fatal(err)
   261  	}
   262  
   263  	if expected := "new data!"; string(b) != expected {
   264  		t.Fatalf("Unexpected test file contents %q, expected %q", string(b), expected)
   265  	}
   266  }
   267  
   268  func assertChange(t *testing.T, actual, expected archive.Change) {
   269  	if actual.Path != expected.Path {
   270  		t.Fatalf("Unexpected change path %s, expected %s", actual.Path, expected.Path)
   271  	}
   272  	if actual.Kind != expected.Kind {
   273  		t.Fatalf("Unexpected change type %s, expected %s", actual.Kind, expected.Kind)
   274  	}
   275  }
   276  
   277  func sortChanges(changes []archive.Change) {
   278  	cs := &changeSorter{
   279  		changes: changes,
   280  	}
   281  	sort.Sort(cs)
   282  }
   283  
   284  type changeSorter struct {
   285  	changes []archive.Change
   286  }
   287  
   288  func (cs *changeSorter) Len() int {
   289  	return len(cs.changes)
   290  }
   291  
   292  func (cs *changeSorter) Swap(i, j int) {
   293  	cs.changes[i], cs.changes[j] = cs.changes[j], cs.changes[i]
   294  }
   295  
   296  func (cs *changeSorter) Less(i, j int) bool {
   297  	return cs.changes[i].Path < cs.changes[j].Path
   298  }