github.com/Files-com/files-sdk-go/v2@v2.1.2/file/pathspec_test.go (about)

     1  package file
     2  
     3  import (
     4  	"bytes"
     5  	"io/ioutil"
     6  	"os"
     7  	"os/exec"
     8  	"path/filepath"
     9  	"strings"
    10  	"sync"
    11  	"testing"
    12  
    13  	"github.com/stretchr/testify/require"
    14  
    15  	"github.com/stretchr/testify/assert"
    16  )
    17  
    18  type pathSpecEntry struct {
    19  	dir         bool
    20  	path        string
    21  	preexisting bool
    22  }
    23  type pathSpecArgs struct {
    24  	src  string
    25  	dest string
    26  }
    27  
    28  type pathSpecTest struct {
    29  	name string
    30  	args pathSpecArgs
    31  	dest []pathSpecEntry
    32  	src  []pathSpecEntry
    33  }
    34  
    35  func pathSpec(srcPathSeparator string, destPathSeparator string) []pathSpecTest {
    36  	return []pathSpecTest{
    37  		{
    38  			name: "copy foo to dest",
    39  			args: pathSpecArgs{
    40  				src:  join(srcPathSeparator, "src", "foo"),
    41  				dest: "dest",
    42  			},
    43  			src: []pathSpecEntry{
    44  				{dir: true, path: "src"},
    45  				{dir: true, path: join(srcPathSeparator, "src", "foo")},
    46  				{dir: false, path: join(srcPathSeparator, "src", "foo", "baz.txt")},
    47  			},
    48  			dest: []pathSpecEntry{
    49  				{dir: true, path: "dest", preexisting: true},
    50  				{dir: true, path: join(destPathSeparator, "dest", "foo")},
    51  				{dir: false, path: join(destPathSeparator, "dest", "foo", "baz.txt")},
    52  			},
    53  		},
    54  		{
    55  			name: "copy contents of foo to dest/foo",
    56  			args: pathSpecArgs{
    57  				src:  join(srcPathSeparator, "src", "foo") + srcPathSeparator,
    58  				dest: join(destPathSeparator, "dest", "foo"),
    59  			},
    60  			src: []pathSpecEntry{
    61  				{dir: true, path: "src"},
    62  				{dir: true, path: join(srcPathSeparator, "src", "foo")},
    63  				{dir: false, path: join(srcPathSeparator, "src", "foo", "baz.txt")},
    64  			},
    65  			dest: []pathSpecEntry{
    66  				{dir: true, path: "dest", preexisting: true},
    67  				{dir: true, path: join(destPathSeparator, "dest", "foo"), preexisting: true},
    68  				{dir: false, path: join(destPathSeparator, "dest", "foo", "baz.txt")},
    69  			},
    70  		},
    71  		{
    72  			name: "copy contents of foo to dest/bar",
    73  			args: pathSpecArgs{
    74  				src:  join(srcPathSeparator, "src", "foo") + srcPathSeparator,
    75  				dest: join(destPathSeparator, "dest", "bar"),
    76  			},
    77  			src: []pathSpecEntry{
    78  				{dir: true, path: "src"},
    79  				{dir: true, path: join(srcPathSeparator, "src", "foo")},
    80  				{dir: false, path: join(srcPathSeparator, "src", "foo", "baz.txt")},
    81  			},
    82  			dest: []pathSpecEntry{
    83  				{dir: true, path: "dest", preexisting: true},
    84  				{dir: true, path: join(destPathSeparator, "dest", "bar"), preexisting: true},
    85  				{dir: false, path: join(destPathSeparator, "dest", "bar", "baz.txt")},
    86  			},
    87  		},
    88  		{
    89  			name: "copy baz.txt to dest",
    90  			args: pathSpecArgs{
    91  				src:  join(srcPathSeparator, "src", "foo", "baz.txt"),
    92  				dest: join(destPathSeparator, "dest", "baz.txt"),
    93  			},
    94  			src: []pathSpecEntry{
    95  				{dir: true, path: join(srcPathSeparator, "src")},
    96  				{dir: true, path: join(srcPathSeparator, "src", "foo")},
    97  				{dir: false, path: join(srcPathSeparator, "src", "foo", "baz.txt")},
    98  			},
    99  			dest: []pathSpecEntry{
   100  				{dir: true, path: "dest", preexisting: true},
   101  				{dir: false, path: join(destPathSeparator, "dest", "baz.txt")},
   102  			},
   103  		},
   104  		{
   105  			name: "copy baz.txt to dest without name",
   106  			args: pathSpecArgs{
   107  				src:  join(srcPathSeparator, "src", "foo", "baz.txt"),
   108  				dest: "dest" + destPathSeparator,
   109  			},
   110  			src: []pathSpecEntry{
   111  				{dir: true, path: "src"},
   112  				{dir: true, path: join(srcPathSeparator, "src", "foo")},
   113  				{dir: false, path: join(srcPathSeparator, "src", "foo", "baz.txt")},
   114  			},
   115  			dest: []pathSpecEntry{
   116  				{dir: true, path: "dest", preexisting: true},
   117  				{dir: false, path: join(destPathSeparator, "dest", "baz.txt")},
   118  			},
   119  		},
   120  		{
   121  			name: "copy baz.txt to dest with rename",
   122  			args: pathSpecArgs{
   123  				src:  join(srcPathSeparator, "src", "foo", "baz.txt"),
   124  				dest: join(destPathSeparator, "dest", "taz.txt"),
   125  			},
   126  			src: []pathSpecEntry{
   127  				{dir: true, path: "src"},
   128  				{dir: true, path: join(srcPathSeparator, "src", "foo")},
   129  				{dir: false, path: join(srcPathSeparator, "src", "foo", "baz.txt")},
   130  			},
   131  			dest: []pathSpecEntry{
   132  				{dir: true, path: "dest", preexisting: true},
   133  				{dir: false, path: join(destPathSeparator, "dest/taz.txt")},
   134  			},
   135  		},
   136  		{
   137  			name: "copy baz.txt to current working directory",
   138  			args: pathSpecArgs{
   139  				src:  join(srcPathSeparator, "src", "foo", "baz.txt"),
   140  				dest: "",
   141  			},
   142  			src: []pathSpecEntry{
   143  				{dir: true, path: "src"},
   144  				{dir: true, path: join(srcPathSeparator, "src", "foo")},
   145  				{dir: false, path: join(srcPathSeparator, "src", "foo", "baz.txt")},
   146  			},
   147  			dest: []pathSpecEntry{
   148  				{dir: false, path: "baz.txt"},
   149  			},
   150  		},
   151  	}
   152  }
   153  
   154  func TestRsync(t *testing.T) {
   155  	_, err := exec.LookPath("rsync")
   156  	if err != nil {
   157  		t.Log(err)
   158  		return
   159  	}
   160  
   161  	t.Run("rsync", func(t *testing.T) {
   162  		mutex := &sync.Mutex{}
   163  		for _, tt := range pathSpec(string(os.PathSeparator), string(os.PathSeparator)) {
   164  			t.Run(tt.name, func(t *testing.T) {
   165  				rsyncSrc, err := ioutil.TempDir("", "rsync-src")
   166  				assert.NoError(t, err)
   167  				rsyncDest, err := ioutil.TempDir("", "rsync-dest")
   168  				assert.NoError(t, err)
   169  
   170  				for _, e := range tt.src {
   171  					if e.dir {
   172  						err = os.MkdirAll(filepath.Join(rsyncSrc, e.path), 0750)
   173  					} else {
   174  						_, err = os.Create(filepath.Join(rsyncSrc, e.path))
   175  					}
   176  					require.NoError(t, err)
   177  				}
   178  				for _, e := range tt.dest {
   179  					if !e.preexisting {
   180  						continue
   181  					}
   182  					if e.dir {
   183  						err = os.MkdirAll(filepath.Join(rsyncDest, e.path), 0750)
   184  					} else {
   185  						_, err = os.Create(filepath.Join(rsyncDest, e.path))
   186  					}
   187  					require.NoError(t, err)
   188  				}
   189  
   190  				source := join(string(os.PathSeparator), rsyncSrc, tt.args.src)
   191  				destination := join(string(os.PathSeparator), rsyncDest, tt.args.dest)
   192  				if tt.args.dest == "" {
   193  					destination = ""
   194  				}
   195  				originalDir, err := os.Getwd()
   196  				require.NoError(t, err)
   197  				mutex.Lock()
   198  				err = os.Chdir(rsyncDest)
   199  				require.NoError(t, err)
   200  				cmd := exec.Command("rsync", "-av", source, destination)
   201  				var cleanedArgs []string
   202  
   203  				for _, arg := range cmd.Args {
   204  					arg = strings.Replace(arg, rsyncSrc, "", 1)
   205  					arg = strings.Replace(arg, rsyncDest, "", 1)
   206  					cleanedArgs = append(cleanedArgs, arg)
   207  				}
   208  				t.Log(cleanedArgs)
   209  				stdout := bytes.NewBufferString("")
   210  				stderr := bytes.NewBufferString("")
   211  				cmd.Stderr = stderr
   212  				cmd.Stdout = stdout
   213  				err = cmd.Run()
   214  				assert.NoError(t, err)
   215  				if stderr.String() != "" {
   216  					t.Log(stderr.String())
   217  				}
   218  				err = os.Chdir(originalDir)
   219  				require.NoError(t, err)
   220  				mutex.Unlock()
   221  				for _, e := range tt.dest {
   222  					fileInfo, err := os.Stat(filepath.Join(rsyncDest, e.path))
   223  					require.NoError(t, err, e.path)
   224  					assert.Equal(t, e.dir, fileInfo.IsDir(), e.path)
   225  				}
   226  
   227  				assert.NoError(t, os.RemoveAll(rsyncSrc))
   228  				assert.NoError(t, os.RemoveAll(rsyncDest))
   229  			})
   230  		}
   231  	})
   232  }
   233  
   234  func join(pathSeparator string, parts ...string) string {
   235  	if parts[len(parts)-1] == pathSeparator {
   236  		return strings.Join(parts, pathSeparator) + pathSeparator
   237  	} else {
   238  		return strings.Join(parts, pathSeparator)
   239  	}
   240  }