2018-11-26 14:08:51 +00:00
|
|
|
// +build go1.9
|
|
|
|
|
2016-02-06 09:22:52 +00:00
|
|
|
package drive
|
|
|
|
|
|
|
|
import (
|
2018-08-19 14:16:11 +00:00
|
|
|
"bytes"
|
2018-01-23 23:46:41 +00:00
|
|
|
"encoding/json"
|
2018-08-19 14:16:11 +00:00
|
|
|
"io"
|
|
|
|
"io/ioutil"
|
2018-02-07 11:53:46 +00:00
|
|
|
"mime"
|
2018-08-19 14:16:11 +00:00
|
|
|
"path/filepath"
|
2018-08-21 10:51:36 +00:00
|
|
|
"strings"
|
2016-02-06 09:22:52 +00:00
|
|
|
"testing"
|
|
|
|
|
2018-08-19 14:16:11 +00:00
|
|
|
_ "github.com/ncw/rclone/backend/local"
|
|
|
|
"github.com/ncw/rclone/fs"
|
|
|
|
"github.com/ncw/rclone/fs/operations"
|
|
|
|
"github.com/ncw/rclone/fstest/fstests"
|
2016-06-12 14:06:02 +00:00
|
|
|
"github.com/pkg/errors"
|
2016-02-06 09:22:52 +00:00
|
|
|
"github.com/stretchr/testify/assert"
|
2018-08-19 14:16:11 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"google.golang.org/api/drive/v3"
|
2016-02-06 09:22:52 +00:00
|
|
|
)
|
|
|
|
|
2019-01-05 20:53:42 +00:00
|
|
|
func TestDriveScopes(t *testing.T) {
|
|
|
|
for _, test := range []struct {
|
|
|
|
in string
|
|
|
|
want []string
|
|
|
|
wantFlag bool
|
|
|
|
}{
|
|
|
|
{"", []string{
|
|
|
|
"https://www.googleapis.com/auth/drive",
|
|
|
|
}, false},
|
|
|
|
{" drive.file , drive.readonly", []string{
|
|
|
|
"https://www.googleapis.com/auth/drive.file",
|
|
|
|
"https://www.googleapis.com/auth/drive.readonly",
|
|
|
|
}, false},
|
|
|
|
{" drive.file , drive.appfolder", []string{
|
|
|
|
"https://www.googleapis.com/auth/drive.file",
|
|
|
|
"https://www.googleapis.com/auth/drive.appfolder",
|
|
|
|
}, true},
|
|
|
|
} {
|
|
|
|
got := driveScopes(test.in)
|
|
|
|
assert.Equal(t, test.want, got, test.in)
|
|
|
|
gotFlag := driveScopesContainsAppFolder(got)
|
|
|
|
assert.Equal(t, test.wantFlag, gotFlag, test.in)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-19 14:16:11 +00:00
|
|
|
/*
|
|
|
|
var additionalMimeTypes = map[string]string{
|
|
|
|
"application/vnd.ms-excel.sheet.macroenabled.12": ".xlsm",
|
|
|
|
"application/vnd.ms-excel.template.macroenabled.12": ".xltm",
|
|
|
|
"application/vnd.ms-powerpoint.presentation.macroenabled.12": ".pptm",
|
|
|
|
"application/vnd.ms-powerpoint.slideshow.macroenabled.12": ".ppsm",
|
|
|
|
"application/vnd.ms-powerpoint.template.macroenabled.12": ".potm",
|
|
|
|
"application/vnd.ms-powerpoint": ".ppt",
|
|
|
|
"application/vnd.ms-word.document.macroenabled.12": ".docm",
|
|
|
|
"application/vnd.ms-word.template.macroenabled.12": ".dotm",
|
|
|
|
"application/vnd.openxmlformats-officedocument.presentationml.template": ".potx",
|
|
|
|
"application/vnd.openxmlformats-officedocument.spreadsheetml.template": ".xltx",
|
|
|
|
"application/vnd.openxmlformats-officedocument.wordprocessingml.template": ".dotx",
|
|
|
|
"application/vnd.sun.xml.writer": ".sxw",
|
|
|
|
"text/richtext": ".rtf",
|
|
|
|
}
|
|
|
|
*/
|
2018-01-31 20:03:02 +00:00
|
|
|
|
|
|
|
// Load the example export formats into exportFormats for testing
|
2018-08-19 14:16:11 +00:00
|
|
|
func TestInternalLoadExampleFormats(t *testing.T) {
|
|
|
|
fetchFormatsOnce.Do(func() {})
|
|
|
|
buf, err := ioutil.ReadFile(filepath.FromSlash("test/about.json"))
|
|
|
|
var about struct {
|
|
|
|
ExportFormats map[string][]string `json:"exportFormats,omitempty"`
|
|
|
|
ImportFormats map[string][]string `json:"importFormats,omitempty"`
|
|
|
|
}
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NoError(t, json.Unmarshal(buf, &about))
|
|
|
|
_exportFormats = fixMimeTypeMap(about.ExportFormats)
|
|
|
|
_importFormats = fixMimeTypeMap(about.ImportFormats)
|
2018-01-31 20:03:02 +00:00
|
|
|
}
|
2018-01-23 23:46:41 +00:00
|
|
|
|
2016-02-06 09:22:52 +00:00
|
|
|
func TestInternalParseExtensions(t *testing.T) {
|
|
|
|
for _, test := range []struct {
|
|
|
|
in string
|
|
|
|
want []string
|
|
|
|
wantErr error
|
|
|
|
}{
|
2018-02-07 11:53:46 +00:00
|
|
|
{"doc", []string{".doc"}, nil},
|
|
|
|
{" docx ,XLSX, pptx,svg", []string{".docx", ".xlsx", ".pptx", ".svg"}, nil},
|
|
|
|
{"docx,svg,Docx", []string{".docx", ".svg"}, nil},
|
|
|
|
{"docx,potato,docx", []string{".docx"}, errors.New(`couldn't find MIME type for extension ".potato"`)},
|
2016-02-06 09:22:52 +00:00
|
|
|
} {
|
2018-08-19 14:16:11 +00:00
|
|
|
extensions, _, gotErr := parseExtensions(test.in)
|
2016-06-12 14:06:02 +00:00
|
|
|
if test.wantErr == nil {
|
|
|
|
assert.NoError(t, gotErr)
|
|
|
|
} else {
|
|
|
|
assert.EqualError(t, gotErr, test.wantErr.Error())
|
|
|
|
}
|
2018-02-07 11:53:46 +00:00
|
|
|
assert.Equal(t, test.want, extensions)
|
2016-02-06 09:22:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Test it is appending
|
2018-08-19 14:16:11 +00:00
|
|
|
extensions, _, gotErr := parseExtensions("docx,svg", "docx,svg,xlsx")
|
2018-02-07 11:53:46 +00:00
|
|
|
assert.NoError(t, gotErr)
|
|
|
|
assert.Equal(t, []string{".docx", ".svg", ".xlsx"}, extensions)
|
2016-02-06 09:22:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestInternalFindExportFormat(t *testing.T) {
|
2018-07-24 15:14:23 +00:00
|
|
|
item := &drive.File{
|
|
|
|
Name: "file",
|
|
|
|
MimeType: "application/vnd.google-apps.document",
|
|
|
|
}
|
2016-02-06 09:22:52 +00:00
|
|
|
for _, test := range []struct {
|
|
|
|
extensions []string
|
|
|
|
wantExtension string
|
2018-01-23 23:46:41 +00:00
|
|
|
wantMimeType string
|
2016-02-06 09:22:52 +00:00
|
|
|
}{
|
|
|
|
{[]string{}, "", ""},
|
2018-02-07 11:53:46 +00:00
|
|
|
{[]string{".pdf"}, ".pdf", "application/pdf"},
|
|
|
|
{[]string{".pdf", ".rtf", ".xls"}, ".pdf", "application/pdf"},
|
|
|
|
{[]string{".xls", ".rtf", ".pdf"}, ".rtf", "application/rtf"},
|
|
|
|
{[]string{".xls", ".csv", ".svg"}, "", ""},
|
2016-02-06 09:22:52 +00:00
|
|
|
} {
|
|
|
|
f := new(Fs)
|
2018-08-19 14:16:11 +00:00
|
|
|
f.exportExtensions = test.extensions
|
2018-07-24 15:14:23 +00:00
|
|
|
gotExtension, gotFilename, gotMimeType, gotIsDocument := f.findExportFormat(item)
|
2016-02-06 09:22:52 +00:00
|
|
|
assert.Equal(t, test.wantExtension, gotExtension)
|
2018-07-24 15:14:23 +00:00
|
|
|
if test.wantExtension != "" {
|
2018-08-19 14:16:11 +00:00
|
|
|
assert.Equal(t, item.Name+gotExtension, gotFilename)
|
2018-07-24 15:14:23 +00:00
|
|
|
} else {
|
|
|
|
assert.Equal(t, "", gotFilename)
|
|
|
|
}
|
2018-01-23 23:46:41 +00:00
|
|
|
assert.Equal(t, test.wantMimeType, gotMimeType)
|
2018-07-24 15:14:23 +00:00
|
|
|
assert.Equal(t, true, gotIsDocument)
|
2016-02-06 09:22:52 +00:00
|
|
|
}
|
|
|
|
}
|
2018-02-07 11:53:46 +00:00
|
|
|
|
|
|
|
func TestMimeTypesToExtension(t *testing.T) {
|
|
|
|
for mimeType, extension := range _mimeTypeToExtension {
|
|
|
|
extensions, err := mime.ExtensionsByType(mimeType)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Contains(t, extensions, extension)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestExtensionToMimeType(t *testing.T) {
|
|
|
|
for mimeType, extension := range _mimeTypeToExtension {
|
|
|
|
gotMimeType := mime.TypeByExtension(extension)
|
|
|
|
mediatype, _, err := mime.ParseMediaType(gotMimeType)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, mimeType, mediatype)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestExtensionsForExportFormats(t *testing.T) {
|
|
|
|
if _exportFormats == nil {
|
|
|
|
t.Error("exportFormats == nil")
|
|
|
|
}
|
|
|
|
for fromMT, toMTs := range _exportFormats {
|
|
|
|
for _, toMT := range toMTs {
|
|
|
|
if !isInternalMimeType(toMT) {
|
|
|
|
extensions, err := mime.ExtensionsByType(toMT)
|
|
|
|
assert.NoError(t, err, "invalid MIME type %q", toMT)
|
|
|
|
assert.NotEmpty(t, extensions, "No extension found for %q (from: %q)", fromMT, toMT)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-08-19 14:16:11 +00:00
|
|
|
|
|
|
|
func TestExtensionsForImportFormats(t *testing.T) {
|
|
|
|
t.Skip()
|
|
|
|
if _importFormats == nil {
|
|
|
|
t.Error("_importFormats == nil")
|
|
|
|
}
|
|
|
|
for fromMT := range _importFormats {
|
|
|
|
if !isInternalMimeType(fromMT) {
|
|
|
|
extensions, err := mime.ExtensionsByType(fromMT)
|
|
|
|
assert.NoError(t, err, "invalid MIME type %q", fromMT)
|
|
|
|
assert.NotEmpty(t, extensions, "No extension found for %q", fromMT)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *Fs) InternalTestDocumentImport(t *testing.T) {
|
|
|
|
oldAllow := f.opt.AllowImportNameChange
|
|
|
|
f.opt.AllowImportNameChange = true
|
|
|
|
defer func() {
|
|
|
|
f.opt.AllowImportNameChange = oldAllow
|
|
|
|
}()
|
|
|
|
|
|
|
|
testFilesPath, err := filepath.Abs(filepath.FromSlash("test/files"))
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
testFilesFs, err := fs.NewFs(testFilesPath)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
_, f.importMimeTypes, err = parseExtensions("odt,ods,doc")
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
err = operations.CopyFile(f, testFilesFs, "example2.doc", "example2.doc")
|
|
|
|
require.NoError(t, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *Fs) InternalTestDocumentUpdate(t *testing.T) {
|
|
|
|
testFilesPath, err := filepath.Abs(filepath.FromSlash("test/files"))
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
testFilesFs, err := fs.NewFs(testFilesPath)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
_, f.importMimeTypes, err = parseExtensions("odt,ods,doc")
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
err = operations.CopyFile(f, testFilesFs, "example2.xlsx", "example1.ods")
|
|
|
|
require.NoError(t, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *Fs) InternalTestDocumentExport(t *testing.T) {
|
|
|
|
var buf bytes.Buffer
|
|
|
|
var err error
|
|
|
|
|
|
|
|
f.exportExtensions, _, err = parseExtensions("txt")
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
obj, err := f.NewObject("example2.txt")
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
rc, err := obj.Open()
|
|
|
|
require.NoError(t, err)
|
|
|
|
defer func() { require.NoError(t, rc.Close()) }()
|
|
|
|
|
|
|
|
_, err = io.Copy(&buf, rc)
|
|
|
|
require.NoError(t, err)
|
|
|
|
text := buf.String()
|
|
|
|
|
|
|
|
for _, excerpt := range []string{
|
|
|
|
"Lorem ipsum dolor sit amet, consectetur",
|
|
|
|
"porta at ultrices in, consectetur at augue.",
|
|
|
|
} {
|
|
|
|
require.Contains(t, text, excerpt)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-21 10:51:36 +00:00
|
|
|
func (f *Fs) InternalTestDocumentLink(t *testing.T) {
|
|
|
|
var buf bytes.Buffer
|
|
|
|
var err error
|
|
|
|
|
|
|
|
f.exportExtensions, _, err = parseExtensions("link.html")
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
obj, err := f.NewObject("example2.link.html")
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
rc, err := obj.Open()
|
|
|
|
require.NoError(t, err)
|
|
|
|
defer func() { require.NoError(t, rc.Close()) }()
|
|
|
|
|
|
|
|
_, err = io.Copy(&buf, rc)
|
|
|
|
require.NoError(t, err)
|
|
|
|
text := buf.String()
|
|
|
|
|
|
|
|
require.True(t, strings.HasPrefix(text, "<html>"))
|
|
|
|
require.True(t, strings.HasSuffix(text, "</html>\n"))
|
|
|
|
for _, excerpt := range []string{
|
|
|
|
`<meta http-equiv="refresh"`,
|
|
|
|
`Loading <a href="`,
|
|
|
|
} {
|
|
|
|
require.Contains(t, text, excerpt)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-19 14:16:11 +00:00
|
|
|
func (f *Fs) InternalTest(t *testing.T) {
|
2018-11-22 17:43:18 +00:00
|
|
|
// These tests all depend on each other so run them as nested tests
|
|
|
|
t.Run("DocumentImport", func(t *testing.T) {
|
|
|
|
f.InternalTestDocumentImport(t)
|
|
|
|
t.Run("DocumentUpdate", func(t *testing.T) {
|
|
|
|
f.InternalTestDocumentUpdate(t)
|
|
|
|
t.Run("DocumentExport", func(t *testing.T) {
|
|
|
|
f.InternalTestDocumentExport(t)
|
|
|
|
t.Run("DocumentLink", func(t *testing.T) {
|
|
|
|
f.InternalTestDocumentLink(t)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
2018-08-19 14:16:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var _ fstests.InternalTester = (*Fs)(nil)
|