github.com/mgoltzsche/ctnr@v0.7.1-alpha/pkg/fs/testutils/writermocks.go (about)

     1  package testutils
     2  
     3  import (
     4  	"net/url"
     5  	"path/filepath"
     6  	"strings"
     7  	"testing"
     8  
     9  	"github.com/mgoltzsche/ctnr/pkg/fs"
    10  	"github.com/stretchr/testify/require"
    11  )
    12  
    13  type TestNode interface {
    14  	Write(fs.Writer) error
    15  }
    16  
    17  func MockWrites(t *testing.T, f TestNode) *WriterMock {
    18  	mockWriter := NewWriterMock(t, fs.AttrsHash)
    19  	err := f.Write(mockWriter)
    20  	require.NoError(t, err)
    21  	return mockWriter
    22  }
    23  
    24  type WriterMock struct {
    25  	t            *testing.T
    26  	Written      []string
    27  	WrittenPaths map[string]bool
    28  	Nodes        []string
    29  	attrs        fs.AttrSet
    30  }
    31  
    32  func NewWriterMock(t *testing.T, attrs fs.AttrSet) *WriterMock {
    33  	return &WriterMock{t, []string{}, map[string]bool{}, []string{}, attrs}
    34  }
    35  func (w *WriterMock) Parent() error {
    36  	return nil
    37  }
    38  func (w *WriterMock) Mkdir(dir string) error {
    39  	return nil
    40  }
    41  func (s *WriterMock) LowerNode(path, name string, a *fs.NodeAttrs) error {
    42  	line := s.opString(a.NodeType, path, &a.FileAttrs)
    43  	if a.Hash != "" {
    44  		line += " hash=" + a.Hash
    45  	}
    46  	if a.URL != "" {
    47  		line += " url=" + a.URL
    48  	}
    49  	if a.HTTPInfo != "" {
    50  		line += " http=" + a.HTTPInfo
    51  	}
    52  	s.Nodes = append(s.Nodes, line)
    53  	return nil
    54  }
    55  func (s *WriterMock) Lazy(path, name string, src fs.LazySource, _ map[fs.Source]string) error {
    56  	a := src.Attrs()
    57  	da, err := src.DeriveAttrs()
    58  	require.NoError(s.t, err)
    59  	require.True(s.t, a.Symlink == "", "%s: link != ''", path)
    60  	require.NotNil(s.t, src, "%s: source not provided", path)
    61  	line := s.opString(a.NodeType, path, &a.FileAttrs) + " hash=" + da.Hash
    62  	s.Nodes = append(s.Nodes, line)
    63  	s.Written = append(s.Written, line)
    64  	s.WrittenPaths[filepath.Clean("/"+path)] = true
    65  	return nil
    66  }
    67  func (s *WriterMock) File(path string, src fs.FileSource) (fs.Source, error) {
    68  	require.NotNil(s.t, src, "%s: source not provided", path)
    69  	a := src.Attrs()
    70  	require.True(s.t, a.Mode != 0 || strings.Contains(path, "blockA") || strings.Contains(path, "chrdevA"), "%s: mode != 0", path)
    71  	require.True(s.t, a.Symlink == "", "%s: link != ''", path)
    72  	line := s.opString("file", path, &a.FileAttrs)
    73  	if s.attrs&fs.AttrsHash != 0 {
    74  		da, err := src.DeriveAttrs()
    75  		require.NoError(s.t, err)
    76  		require.True(s.t, da.Hash != "" || da.HTTPInfo != "", "%s: hash|http == ''; hash=%q, http=%q", path, da.Hash, da.HTTPInfo)
    77  		if da.Hash != "" {
    78  			line += " hash=" + da.Hash
    79  		}
    80  		if da.URL != "" {
    81  			line += " url=" + da.URL
    82  		}
    83  		if da.HTTPInfo != "" {
    84  			line += " http=" + da.HTTPInfo
    85  		}
    86  	}
    87  	s.Nodes = append(s.Nodes, line)
    88  	s.Written = append(s.Written, line)
    89  	s.WrittenPaths[filepath.Clean("/"+path)] = true
    90  	return src, nil
    91  }
    92  func (s *WriterMock) Link(path, target string) error {
    93  	s.link(path, target)
    94  	line := path + " hlink=" + target
    95  	s.Written = append(s.Written, line)
    96  	s.WrittenPaths[filepath.Clean("/"+path)] = true
    97  	return nil
    98  }
    99  func (s *WriterMock) LowerLink(path, target string, a *fs.NodeAttrs) error {
   100  	s.link(path, target)
   101  	return nil
   102  }
   103  func (s *WriterMock) link(path, target string) {
   104  	require.True(s.t, target != "", "%s: link target must be provided", path)
   105  	line := path + " hlink=" + target
   106  	s.Nodes = append(s.Nodes, line)
   107  }
   108  func (s *WriterMock) Symlink(path string, a fs.FileAttrs) error {
   109  	require.True(s.t, a.Symlink != "", "%s: symlink dest must be provided", path)
   110  	line := s.opString(fs.TypeSymlink, path, &a)
   111  	s.Nodes = append(s.Nodes, line)
   112  	s.Written = append(s.Written, line)
   113  	s.WrittenPaths[filepath.Clean("/"+path)] = true
   114  	return nil
   115  }
   116  func (s *WriterMock) Dir(path, name string, a fs.FileAttrs) error {
   117  	require.True(s.t, a.Mode != 0, "%s: mode != 0", path)
   118  	require.True(s.t, a.Symlink == "", "%s: link != ''", path)
   119  	line := s.opString(fs.TypeDir, path, &a)
   120  	s.Nodes = append(s.Nodes, line)
   121  	s.Written = append(s.Written, line)
   122  	s.WrittenPaths[filepath.Clean("/"+path)] = true
   123  	return nil
   124  }
   125  func (s *WriterMock) Fifo(path string, a fs.DeviceAttrs) error {
   126  	line := s.opString(fs.TypeFifo, path, &a.FileAttrs)
   127  	s.Nodes = append(s.Nodes, line)
   128  	s.Written = append(s.Written, line)
   129  	s.WrittenPaths[filepath.Clean("/"+path)] = true
   130  	return nil
   131  }
   132  func (s *WriterMock) Device(path string, a fs.DeviceAttrs) error {
   133  	line := s.opString(fs.TypeDevice, path, &a.FileAttrs)
   134  	s.Nodes = append(s.Nodes, line)
   135  	s.Written = append(s.Written, line)
   136  	s.WrittenPaths[filepath.Clean("/"+path)] = true
   137  	return nil
   138  }
   139  func (s *WriterMock) Remove(path string) error {
   140  	line := path + " type=whiteout"
   141  	s.Nodes = append(s.Nodes, line)
   142  	s.Written = append(s.Written, line)
   143  	s.WrittenPaths[filepath.Clean("/"+path)] = true
   144  	return nil
   145  }
   146  func (s *WriterMock) opString(t fs.NodeType, path string, a *fs.FileAttrs) string {
   147  	return encodePath(path) + " " + (&fs.NodeInfo{t, *a}).AttrString(s.attrs)
   148  }
   149  
   150  type ExpandingWriterMock struct {
   151  	*WriterMock
   152  }
   153  
   154  func (s *ExpandingWriterMock) Lazy(path, name string, src fs.LazySource, written map[fs.Source]string) error {
   155  	return src.Expand(path, s, written)
   156  }
   157  
   158  func encodePath(p string) string {
   159  	l := strings.Split(p, string(filepath.Separator))
   160  	for i, s := range l {
   161  		l[i] = url.PathEscape(s)
   162  	}
   163  	return strings.Join(l, string(filepath.Separator))
   164  }