github.com/ncw/rclone@v1.48.1-0.20190724201158-a35aa1360e3e/backend/googlephotos/googlephotos_test.go (about)

     1  package googlephotos
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"net/http"
     8  	"path"
     9  	"testing"
    10  	"time"
    11  
    12  	_ "github.com/ncw/rclone/backend/local"
    13  	"github.com/ncw/rclone/fs"
    14  	"github.com/ncw/rclone/fs/hash"
    15  	"github.com/ncw/rclone/fstest"
    16  	"github.com/stretchr/testify/assert"
    17  	"github.com/stretchr/testify/require"
    18  )
    19  
    20  const (
    21  	// We have two different files here as Google Photos will uniq
    22  	// them otherwise which confuses the tests as the filename is
    23  	// unexpected.
    24  	fileNameAlbum  = "rclone-test-image1.jpg"
    25  	fileNameUpload = "rclone-test-image2.jpg"
    26  )
    27  
    28  // Wrapper to override the remote for an object
    29  type overrideRemoteObject struct {
    30  	fs.Object
    31  	remote string
    32  }
    33  
    34  // Remote returns the overridden remote name
    35  func (o *overrideRemoteObject) Remote() string {
    36  	return o.remote
    37  }
    38  
    39  func TestIntegration(t *testing.T) {
    40  	ctx := context.Background()
    41  	fstest.Initialise()
    42  
    43  	// Create Fs
    44  	if *fstest.RemoteName == "" {
    45  		*fstest.RemoteName = "TestGooglePhotos:"
    46  	}
    47  	f, err := fs.NewFs(*fstest.RemoteName)
    48  	if err == fs.ErrorNotFoundInConfigFile {
    49  		t.Skip(fmt.Sprintf("Couldn't create google photos backend - skipping tests: %v", err))
    50  	}
    51  	require.NoError(t, err)
    52  
    53  	// Create local Fs pointing at testfiles
    54  	localFs, err := fs.NewFs("testfiles")
    55  	require.NoError(t, err)
    56  
    57  	t.Run("CreateAlbum", func(t *testing.T) {
    58  		albumName := "album/rclone-test-" + fstest.RandomString(24)
    59  		err = f.Mkdir(ctx, albumName)
    60  		require.NoError(t, err)
    61  		remote := albumName + "/" + fileNameAlbum
    62  
    63  		t.Run("PutFile", func(t *testing.T) {
    64  			srcObj, err := localFs.NewObject(ctx, fileNameAlbum)
    65  			require.NoError(t, err)
    66  			in, err := srcObj.Open(ctx)
    67  			require.NoError(t, err)
    68  			dstObj, err := f.Put(ctx, in, &overrideRemoteObject{srcObj, remote})
    69  			require.NoError(t, err)
    70  			assert.Equal(t, remote, dstObj.Remote())
    71  			_ = in.Close()
    72  			remoteWithID := addFileID(remote, dstObj.(*Object).id)
    73  
    74  			t.Run("ObjectFs", func(t *testing.T) {
    75  				assert.Equal(t, f, dstObj.Fs())
    76  			})
    77  
    78  			t.Run("ObjectString", func(t *testing.T) {
    79  				assert.Equal(t, remote, dstObj.String())
    80  				assert.Equal(t, "<nil>", (*Object)(nil).String())
    81  			})
    82  
    83  			t.Run("ObjectHash", func(t *testing.T) {
    84  				h, err := dstObj.Hash(ctx, hash.MD5)
    85  				assert.Equal(t, "", h)
    86  				assert.Equal(t, hash.ErrUnsupported, err)
    87  			})
    88  
    89  			t.Run("ObjectSize", func(t *testing.T) {
    90  				assert.Equal(t, int64(-1), dstObj.Size())
    91  				f.(*Fs).opt.ReadSize = true
    92  				defer func() {
    93  					f.(*Fs).opt.ReadSize = false
    94  				}()
    95  				size := dstObj.Size()
    96  				assert.True(t, size > 1000, fmt.Sprintf("Size too small %d", size))
    97  			})
    98  
    99  			t.Run("ObjectSetModTime", func(t *testing.T) {
   100  				err := dstObj.SetModTime(ctx, time.Now())
   101  				assert.Equal(t, fs.ErrorCantSetModTime, err)
   102  			})
   103  
   104  			t.Run("ObjectStorable", func(t *testing.T) {
   105  				assert.True(t, dstObj.Storable())
   106  			})
   107  
   108  			t.Run("ObjectOpen", func(t *testing.T) {
   109  				in, err := dstObj.Open(ctx)
   110  				require.NoError(t, err)
   111  				buf, err := ioutil.ReadAll(in)
   112  				require.NoError(t, err)
   113  				require.NoError(t, in.Close())
   114  				assert.True(t, len(buf) > 1000)
   115  				contentType := http.DetectContentType(buf[:512])
   116  				assert.Equal(t, "image/jpeg", contentType)
   117  			})
   118  
   119  			t.Run("CheckFileInAlbum", func(t *testing.T) {
   120  				entries, err := f.List(ctx, albumName)
   121  				require.NoError(t, err)
   122  				assert.Equal(t, 1, len(entries))
   123  				assert.Equal(t, remote, entries[0].Remote())
   124  				assert.Equal(t, "2013-07-26 08:57:21 +0000 UTC", entries[0].ModTime(ctx).String())
   125  			})
   126  
   127  			// Check it is there in the date/month/year heirachy
   128  			// 2013-07-13 is the creation date of the folder
   129  			checkPresent := func(t *testing.T, objPath string) {
   130  				entries, err := f.List(ctx, objPath)
   131  				require.NoError(t, err)
   132  				found := false
   133  				for _, entry := range entries {
   134  					leaf := path.Base(entry.Remote())
   135  					if leaf == fileNameAlbum || leaf == remoteWithID {
   136  						found = true
   137  					}
   138  				}
   139  				assert.True(t, found, fmt.Sprintf("didn't find %q in %q", fileNameAlbum, objPath))
   140  			}
   141  
   142  			t.Run("CheckInByYear", func(t *testing.T) {
   143  				checkPresent(t, "media/by-year/2013")
   144  			})
   145  
   146  			t.Run("CheckInByMonth", func(t *testing.T) {
   147  				checkPresent(t, "media/by-month/2013/2013-07")
   148  			})
   149  
   150  			t.Run("CheckInByDay", func(t *testing.T) {
   151  				checkPresent(t, "media/by-day/2013/2013-07-26")
   152  			})
   153  
   154  			t.Run("NewObject", func(t *testing.T) {
   155  				o, err := f.NewObject(ctx, remote)
   156  				require.NoError(t, err)
   157  				require.Equal(t, remote, o.Remote())
   158  			})
   159  
   160  			t.Run("NewObjectWithID", func(t *testing.T) {
   161  				o, err := f.NewObject(ctx, remoteWithID)
   162  				require.NoError(t, err)
   163  				require.Equal(t, remoteWithID, o.Remote())
   164  			})
   165  
   166  			t.Run("NewFsIsFile", func(t *testing.T) {
   167  				fNew, err := fs.NewFs(*fstest.RemoteName + remote)
   168  				assert.Equal(t, fs.ErrorIsFile, err)
   169  				leaf := path.Base(remote)
   170  				o, err := fNew.NewObject(ctx, leaf)
   171  				require.NoError(t, err)
   172  				require.Equal(t, leaf, o.Remote())
   173  			})
   174  
   175  			t.Run("RemoveFileFromAlbum", func(t *testing.T) {
   176  				err = dstObj.Remove(ctx)
   177  				require.NoError(t, err)
   178  
   179  				time.Sleep(time.Second)
   180  
   181  				// Check album empty
   182  				entries, err := f.List(ctx, albumName)
   183  				require.NoError(t, err)
   184  				assert.Equal(t, 0, len(entries))
   185  			})
   186  		})
   187  
   188  		// remove the album
   189  		err = f.Rmdir(ctx, albumName)
   190  		require.Error(t, err) // FIXME doesn't work yet
   191  	})
   192  
   193  	t.Run("UploadMkdir", func(t *testing.T) {
   194  		assert.NoError(t, f.Mkdir(ctx, "upload/dir"))
   195  		assert.NoError(t, f.Mkdir(ctx, "upload/dir/subdir"))
   196  
   197  		t.Run("List", func(t *testing.T) {
   198  			entries, err := f.List(ctx, "upload")
   199  			require.NoError(t, err)
   200  			assert.Equal(t, 1, len(entries))
   201  			assert.Equal(t, "upload/dir", entries[0].Remote())
   202  
   203  			entries, err = f.List(ctx, "upload/dir")
   204  			require.NoError(t, err)
   205  			assert.Equal(t, 1, len(entries))
   206  			assert.Equal(t, "upload/dir/subdir", entries[0].Remote())
   207  		})
   208  
   209  		t.Run("Rmdir", func(t *testing.T) {
   210  			assert.NoError(t, f.Rmdir(ctx, "upload/dir/subdir"))
   211  			assert.NoError(t, f.Rmdir(ctx, "upload/dir"))
   212  
   213  		})
   214  
   215  		t.Run("ListEmpty", func(t *testing.T) {
   216  			entries, err := f.List(ctx, "upload")
   217  			require.NoError(t, err)
   218  			assert.Equal(t, 0, len(entries))
   219  
   220  			_, err = f.List(ctx, "upload/dir")
   221  			assert.Equal(t, fs.ErrorDirNotFound, err)
   222  		})
   223  	})
   224  
   225  	t.Run("Upload", func(t *testing.T) {
   226  		uploadDir := "upload/dir/subdir"
   227  		remote := path.Join(uploadDir, fileNameUpload)
   228  
   229  		srcObj, err := localFs.NewObject(ctx, fileNameUpload)
   230  		require.NoError(t, err)
   231  		in, err := srcObj.Open(ctx)
   232  		require.NoError(t, err)
   233  		dstObj, err := f.Put(ctx, in, &overrideRemoteObject{srcObj, remote})
   234  		require.NoError(t, err)
   235  		assert.Equal(t, remote, dstObj.Remote())
   236  		_ = in.Close()
   237  		remoteWithID := addFileID(remote, dstObj.(*Object).id)
   238  
   239  		t.Run("List", func(t *testing.T) {
   240  			entries, err := f.List(ctx, uploadDir)
   241  			require.NoError(t, err)
   242  			require.Equal(t, 1, len(entries))
   243  			assert.Equal(t, remote, entries[0].Remote())
   244  			assert.Equal(t, "2013-07-26 08:57:21 +0000 UTC", entries[0].ModTime(ctx).String())
   245  		})
   246  
   247  		t.Run("NewObject", func(t *testing.T) {
   248  			o, err := f.NewObject(ctx, remote)
   249  			require.NoError(t, err)
   250  			require.Equal(t, remote, o.Remote())
   251  		})
   252  
   253  		t.Run("NewObjectWithID", func(t *testing.T) {
   254  			o, err := f.NewObject(ctx, remoteWithID)
   255  			require.NoError(t, err)
   256  			require.Equal(t, remoteWithID, o.Remote())
   257  		})
   258  
   259  	})
   260  
   261  	t.Run("Name", func(t *testing.T) {
   262  		assert.Equal(t, (*fstest.RemoteName)[:len(*fstest.RemoteName)-1], f.Name())
   263  	})
   264  
   265  	t.Run("Root", func(t *testing.T) {
   266  		assert.Equal(t, "", f.Root())
   267  	})
   268  
   269  	t.Run("String", func(t *testing.T) {
   270  		assert.Equal(t, `Google Photos path ""`, f.String())
   271  	})
   272  
   273  	t.Run("Features", func(t *testing.T) {
   274  		features := f.Features()
   275  		assert.False(t, features.CaseInsensitive)
   276  		assert.True(t, features.ReadMimeType)
   277  	})
   278  
   279  	t.Run("Precision", func(t *testing.T) {
   280  		assert.Equal(t, fs.ModTimeNotSupported, f.Precision())
   281  	})
   282  
   283  	t.Run("Hashes", func(t *testing.T) {
   284  		assert.Equal(t, hash.Set(hash.None), f.Hashes())
   285  	})
   286  
   287  }
   288  
   289  func TestAddID(t *testing.T) {
   290  	assert.Equal(t, "potato {123}", addID("potato", "123"))
   291  	assert.Equal(t, "{123}", addID("", "123"))
   292  }
   293  
   294  func TestFileAddID(t *testing.T) {
   295  	assert.Equal(t, "potato {123}.txt", addFileID("potato.txt", "123"))
   296  	assert.Equal(t, "potato {123}", addFileID("potato", "123"))
   297  	assert.Equal(t, "{123}", addFileID("", "123"))
   298  }
   299  
   300  func TestFindID(t *testing.T) {
   301  	assert.Equal(t, "", findID("potato"))
   302  	ID := "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
   303  	assert.Equal(t, ID, findID("potato {"+ID+"}.txt"))
   304  	ID = ID[1:]
   305  	assert.Equal(t, "", findID("potato {"+ID+"}.txt"))
   306  }