test: add unit tests, adjust fileinfo

This commit is contained in:
Juan Pablo Villafáñez
2024-03-27 17:35:30 +01:00
parent d85d24b5c5
commit 710a0b4561
7 changed files with 1457 additions and 1 deletions

View File

@@ -0,0 +1,13 @@
package connector_test
import (
"testing"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
func TestGraph(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Connector Suite")
}

View File

@@ -0,0 +1,418 @@
package connector_test
import (
"context"
"errors"
"net/http"
"net/http/httptest"
"strings"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/stretchr/testify/mock"
appproviderv1beta1 "github.com/cs3org/go-cs3apis/cs3/app/provider/v1beta1"
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
userv1beta1 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
providerv1beta1 "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
"github.com/cs3org/reva/v2/pkg/rgrpc/status"
"github.com/owncloud/ocis/v2/services/collaboration/pkg/config"
"github.com/owncloud/ocis/v2/services/collaboration/pkg/connector"
"github.com/owncloud/ocis/v2/services/collaboration/pkg/middleware"
cs3mocks "github.com/cs3org/reva/v2/tests/cs3mocks/mocks"
)
var _ = Describe("ContentConnector", func() {
var (
cc *connector.ContentConnector
gatewayClient *cs3mocks.GatewayAPIClient
cfg *config.Config
wopiCtx middleware.WopiContext
srv *httptest.Server
srvReqHeader http.Header
randomContent string
)
BeforeEach(func() {
// contentConnector only uses "cfg.CS3Api.DataGateway.Insecure", which is irrelevant for the tests
cfg = &config.Config{}
gatewayClient = &cs3mocks.GatewayAPIClient{}
cc = connector.NewContentConnector(gatewayClient, cfg)
wopiCtx = middleware.WopiContext{
AccessToken: "abcdef123456",
FileReference: providerv1beta1.Reference{
ResourceId: &providerv1beta1.ResourceId{
StorageId: "abc",
OpaqueId: "12345",
SpaceId: "zzz",
},
Path: ".",
},
User: &userv1beta1.User{}, // Not used for now
ViewMode: appproviderv1beta1.ViewMode_VIEW_MODE_READ_WRITE,
EditAppUrl: "http://test.ex.prv/edit",
ViewAppUrl: "http://test.ex.prv/view",
}
randomContent = "This is the content of the test.txt file"
srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
srvReqHeader = req.Header // save the request header to check later
switch req.URL.Path {
case "/download/failed.png":
w.WriteHeader(404)
case "/download/test.txt":
w.Write([]byte(randomContent))
case "/upload/failed.png":
w.WriteHeader(404)
case "/upload/test.txt":
w.WriteHeader(200)
}
}))
})
AfterEach(func() {
srv.Close()
})
Describe("GetFile", func() {
It("No valid context", func() {
sb := &strings.Builder{}
ctx := context.Background()
err := cc.GetFile(ctx, sb)
Expect(err).To(HaveOccurred())
})
It("Initiate download failed", func() {
sb := &strings.Builder{}
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
targetErr := errors.New("Something went wrong")
gatewayClient.On("InitiateFileDownload", mock.Anything, mock.Anything).Times(1).Return(&gateway.InitiateFileDownloadResponse{
Status: status.NewInternal(ctx, "Something failed"),
}, targetErr)
err := cc.GetFile(ctx, sb)
Expect(err).To(Equal(targetErr))
})
It("Initiate download status not ok", func() {
sb := &strings.Builder{}
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("InitiateFileDownload", mock.Anything, mock.Anything).Times(1).Return(&gateway.InitiateFileDownloadResponse{
Status: status.NewInternal(ctx, "Something failed"),
}, nil)
err := cc.GetFile(ctx, sb)
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(500))
})
It("Missing download endpoint", func() {
sb := &strings.Builder{}
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("InitiateFileDownload", mock.Anything, mock.Anything).Times(1).Return(&gateway.InitiateFileDownloadResponse{
Status: status.NewOK(ctx),
}, nil)
err := cc.GetFile(ctx, sb)
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(500))
})
It("Download request failed", func() {
sb := &strings.Builder{}
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("InitiateFileDownload", mock.Anything, mock.Anything).Times(1).Return(&gateway.InitiateFileDownloadResponse{
Status: status.NewOK(ctx),
Protocols: []*gateway.FileDownloadProtocol{
&gateway.FileDownloadProtocol{
Protocol: "simple",
DownloadEndpoint: srv.URL + "/download/failed.png",
Token: "MyDownloadToken",
},
},
}, nil)
err := cc.GetFile(ctx, sb)
Expect(srvReqHeader.Get("X-Access-Token")).To(Equal(wopiCtx.AccessToken))
Expect(srvReqHeader.Get("X-Reva-Transfer")).To(Equal("MyDownloadToken"))
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(500))
})
It("Download request success", func() {
sb := &strings.Builder{}
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("InitiateFileDownload", mock.Anything, mock.Anything).Times(1).Return(&gateway.InitiateFileDownloadResponse{
Status: status.NewOK(ctx),
Protocols: []*gateway.FileDownloadProtocol{
&gateway.FileDownloadProtocol{
Protocol: "simple",
DownloadEndpoint: srv.URL + "/download/test.txt",
Token: "MyDownloadToken",
},
},
}, nil)
err := cc.GetFile(ctx, sb)
Expect(srvReqHeader.Get("X-Access-Token")).To(Equal(wopiCtx.AccessToken))
Expect(srvReqHeader.Get("X-Reva-Transfer")).To(Equal("MyDownloadToken"))
Expect(err).To(Succeed())
Expect(sb.String()).To(Equal(randomContent))
})
})
Describe("PutFile", func() {
It("No valid context", func() {
reader := strings.NewReader("Content to upload is here!")
ctx := context.Background()
newLockId, err := cc.PutFile(ctx, reader, reader.Size(), "notARandomLockId")
Expect(err).To(HaveOccurred())
Expect(newLockId).To(Equal(""))
})
It("Stat call failed", func() {
reader := strings.NewReader("Content to upload is here!")
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
targetErr := errors.New("Something went wrong")
gatewayClient.On("Stat", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.StatResponse{
Status: status.NewInternal(ctx, "Something failed"),
}, targetErr)
newLockId, err := cc.PutFile(ctx, reader, reader.Size(), "notARandomLockId")
Expect(err).To(Equal(targetErr))
Expect(newLockId).To(Equal(""))
})
It("Stat call status not ok", func() {
reader := strings.NewReader("Content to upload is here!")
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("Stat", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.StatResponse{
Status: status.NewInternal(ctx, "Something failed"),
}, nil)
newLockId, err := cc.PutFile(ctx, reader, reader.Size(), "notARandomLockId")
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(500))
Expect(newLockId).To(Equal(""))
})
It("Mismatched lockId", func() {
reader := strings.NewReader("Content to upload is here!")
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("Stat", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.StatResponse{
Status: status.NewOK(ctx),
Info: &providerv1beta1.ResourceInfo{
Lock: &providerv1beta1.Lock{
LockId: "goodAndValidLock",
Type: providerv1beta1.LockType_LOCK_TYPE_WRITE,
},
},
}, nil)
newLockId, err := cc.PutFile(ctx, reader, reader.Size(), "notARandomLockId")
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(409))
Expect(newLockId).To(Equal("goodAndValidLock"))
})
It("Upload without lockId but on a non empty file", func() {
reader := strings.NewReader("Content to upload is here!")
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("Stat", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.StatResponse{
Status: status.NewOK(ctx),
Info: &providerv1beta1.ResourceInfo{
Lock: nil,
Size: uint64(123456789),
},
}, nil)
newLockId, err := cc.PutFile(ctx, reader, reader.Size(), "")
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(409))
Expect(newLockId).To(Equal(""))
})
It("Initiate upload fails", func() {
reader := strings.NewReader("Content to upload is here!")
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("Stat", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.StatResponse{
Status: status.NewOK(ctx),
Info: &providerv1beta1.ResourceInfo{
Lock: &providerv1beta1.Lock{
LockId: "goodAndValidLock",
Type: providerv1beta1.LockType_LOCK_TYPE_WRITE,
},
Size: uint64(123456789),
},
}, nil)
targetErr := errors.New("Something went wrong")
gatewayClient.On("InitiateFileUpload", mock.Anything, mock.Anything).Times(1).Return(&gateway.InitiateFileUploadResponse{
Status: status.NewInternal(ctx, "Something failed"),
}, targetErr)
newLockId, err := cc.PutFile(ctx, reader, reader.Size(), "goodAndValidLock")
Expect(err).To(HaveOccurred())
Expect(newLockId).To(Equal(""))
})
It("Initiate upload status not ok", func() {
reader := strings.NewReader("Content to upload is here!")
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("Stat", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.StatResponse{
Status: status.NewOK(ctx),
Info: &providerv1beta1.ResourceInfo{
Lock: &providerv1beta1.Lock{
LockId: "goodAndValidLock",
Type: providerv1beta1.LockType_LOCK_TYPE_WRITE,
},
Size: uint64(123456789),
},
}, nil)
gatewayClient.On("InitiateFileUpload", mock.Anything, mock.Anything).Times(1).Return(&gateway.InitiateFileUploadResponse{
Status: status.NewInternal(ctx, "Something failed"),
}, nil)
newLockId, err := cc.PutFile(ctx, reader, reader.Size(), "goodAndValidLock")
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(500))
Expect(newLockId).To(Equal(""))
})
It("Empty upload successful", func() {
reader := strings.NewReader("")
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("Stat", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.StatResponse{
Status: status.NewOK(ctx),
Info: &providerv1beta1.ResourceInfo{
Lock: &providerv1beta1.Lock{
LockId: "goodAndValidLock",
Type: providerv1beta1.LockType_LOCK_TYPE_WRITE,
},
Size: uint64(123456789),
},
}, nil)
gatewayClient.On("InitiateFileUpload", mock.Anything, mock.Anything).Times(1).Return(&gateway.InitiateFileUploadResponse{
Status: status.NewOK(ctx),
}, nil)
newLockId, err := cc.PutFile(ctx, reader, reader.Size(), "goodAndValidLock")
Expect(err).To(Succeed())
Expect(newLockId).To(Equal(""))
})
It("Missing upload endpoint", func() {
reader := strings.NewReader("Content to upload is here!")
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("Stat", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.StatResponse{
Status: status.NewOK(ctx),
Info: &providerv1beta1.ResourceInfo{
Lock: &providerv1beta1.Lock{
LockId: "goodAndValidLock",
Type: providerv1beta1.LockType_LOCK_TYPE_WRITE,
},
Size: uint64(123456789),
},
}, nil)
gatewayClient.On("InitiateFileUpload", mock.Anything, mock.Anything).Times(1).Return(&gateway.InitiateFileUploadResponse{
Status: status.NewOK(ctx),
}, nil)
newLockId, err := cc.PutFile(ctx, reader, reader.Size(), "goodAndValidLock")
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(500))
Expect(newLockId).To(Equal(""))
})
It("upload request failed", func() {
reader := strings.NewReader("Content to upload is here!")
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("Stat", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.StatResponse{
Status: status.NewOK(ctx),
Info: &providerv1beta1.ResourceInfo{
Lock: &providerv1beta1.Lock{
LockId: "goodAndValidLock",
Type: providerv1beta1.LockType_LOCK_TYPE_WRITE,
},
Size: uint64(123456789),
},
}, nil)
gatewayClient.On("InitiateFileUpload", mock.Anything, mock.Anything).Times(1).Return(&gateway.InitiateFileUploadResponse{
Status: status.NewOK(ctx),
Protocols: []*gateway.FileUploadProtocol{
&gateway.FileUploadProtocol{
Protocol: "simple",
UploadEndpoint: srv.URL + "/upload/failed.png",
},
},
}, nil)
newLockId, err := cc.PutFile(ctx, reader, reader.Size(), "goodAndValidLock")
Expect(srvReqHeader.Get("X-Access-Token")).To(Equal(wopiCtx.AccessToken))
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(500))
Expect(newLockId).To(Equal(""))
})
It("upload request success", func() {
reader := strings.NewReader("Content to upload is here!")
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("Stat", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.StatResponse{
Status: status.NewOK(ctx),
Info: &providerv1beta1.ResourceInfo{
Lock: &providerv1beta1.Lock{
LockId: "goodAndValidLock",
Type: providerv1beta1.LockType_LOCK_TYPE_WRITE,
},
Size: uint64(123456789),
},
}, nil)
gatewayClient.On("InitiateFileUpload", mock.Anything, mock.Anything).Times(1).Return(&gateway.InitiateFileUploadResponse{
Status: status.NewOK(ctx),
Protocols: []*gateway.FileUploadProtocol{
&gateway.FileUploadProtocol{
Protocol: "simple",
UploadEndpoint: srv.URL + "/upload/test.txt",
},
},
}, nil)
newLockId, err := cc.PutFile(ctx, reader, reader.Size(), "goodAndValidLock")
Expect(srvReqHeader.Get("X-Access-Token")).To(Equal(wopiCtx.AccessToken))
Expect(err).To(Succeed())
Expect(newLockId).To(Equal(""))
})
})
})

View File

@@ -4,6 +4,7 @@ import (
"context"
"encoding/hex"
"path"
"strconv"
"time"
appproviderv1beta1 "github.com/cs3org/go-cs3apis/cs3/app/provider/v1beta1"
@@ -69,6 +70,7 @@ func (f *FileConnector) GetLock(ctx context.Context) (string, error) {
Str("StatusCode", resp.GetStatus().GetCode().String()).
Str("StatusMsg", resp.GetStatus().GetMessage()).
Msg("GetLock failed with unexpected status")
// TODO: Should we be more strict? There could be more causes for the failure
return "", NewConnectorError(404, resp.GetStatus().GetCode().String()+" "+resp.GetStatus().GetMessage())
}
@@ -469,7 +471,7 @@ func (f *FileConnector) CheckFileInfo(ctx context.Context) (FileInfo, error) {
// OwnerId must use only alphanumeric chars (https://learn.microsoft.com/en-us/microsoft-365/cloud-storage-partner-program/rest/files/checkfileinfo/checkfileinfo-response#requirements-for-user-identity-properties)
OwnerId: hex.EncodeToString([]byte(statRes.GetInfo().GetOwner().GetOpaqueId() + "@" + statRes.GetInfo().GetOwner().GetIdp())),
Size: int64(statRes.GetInfo().GetSize()),
Version: statRes.GetInfo().GetMtime().String(),
Version: strconv.FormatUint(statRes.GetInfo().GetMtime().GetSeconds(), 10) + "." + strconv.FormatUint(uint64(statRes.GetInfo().GetMtime().GetNanos()), 10),
BaseFileName: path.Base(statRes.GetInfo().GetPath()),
BreadcrumbDocName: path.Base(statRes.GetInfo().GetPath()),
// to get the folder we actually need to do a GetPath() request

View File

@@ -0,0 +1,875 @@
package connector_test
import (
"context"
"encoding/hex"
"errors"
appproviderv1beta1 "github.com/cs3org/go-cs3apis/cs3/app/provider/v1beta1"
userv1beta1 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
providerv1beta1 "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
typesv1beta1 "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
"github.com/cs3org/reva/v2/pkg/rgrpc/status"
cs3mocks "github.com/cs3org/reva/v2/tests/cs3mocks/mocks"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/owncloud/ocis/v2/services/collaboration/pkg/config"
"github.com/owncloud/ocis/v2/services/collaboration/pkg/connector"
"github.com/owncloud/ocis/v2/services/collaboration/pkg/middleware"
"github.com/stretchr/testify/mock"
)
var _ = Describe("FileConnector", func() {
var (
fc *connector.FileConnector
gatewayClient *cs3mocks.GatewayAPIClient
cfg *config.Config
wopiCtx middleware.WopiContext
)
BeforeEach(func() {
cfg = &config.Config{
App: config.App{
LockName: "testName_for_unittests", // Only the LockName is used
},
}
gatewayClient = &cs3mocks.GatewayAPIClient{}
fc = connector.NewFileConnector(gatewayClient, cfg)
wopiCtx = middleware.WopiContext{
AccessToken: "abcdef123456",
FileReference: providerv1beta1.Reference{
ResourceId: &providerv1beta1.ResourceId{
StorageId: "abc",
OpaqueId: "12345",
SpaceId: "zzz",
},
Path: ".",
},
User: &userv1beta1.User{
Id: &userv1beta1.UserId{
Idp: "inmemory",
OpaqueId: "opaqueId",
Type: userv1beta1.UserType_USER_TYPE_PRIMARY,
},
Username: "Pet Shaft",
// Opaque is here for reference, not used by default but might be needed for some tests
//Opaque: &typesv1beta1.Opaque{
// Map: map[string]*typesv1beta1.OpaqueEntry{
// "public-share-role": &typesv1beta1.OpaqueEntry{
// Decoder: "plain",
// Value: []byte("viewer"),
// },
// },
//},
},
ViewMode: appproviderv1beta1.ViewMode_VIEW_MODE_READ_WRITE,
EditAppUrl: "http://test.ex.prv/edit",
ViewAppUrl: "http://test.ex.prv/view",
}
})
Describe("GetLock", func() {
It("No valid context", func() {
ctx := context.Background()
newLockId, err := fc.GetLock(ctx)
Expect(err).To(HaveOccurred())
Expect(newLockId).To(Equal(""))
})
It("Get lock failed", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
targetErr := errors.New("Something went wrong")
gatewayClient.On("GetLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.GetLockResponse{
Status: status.NewInternal(ctx, "Something failed"),
}, targetErr)
newLockId, err := fc.GetLock(ctx)
Expect(err).To(Equal(targetErr))
Expect(newLockId).To(Equal(""))
})
It("Get lock failed status not ok", func() {
// assume failure happens because the target file doesn't exists
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("GetLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.GetLockResponse{
Status: status.NewNotFound(ctx, "File is missing"),
}, nil)
newLockId, err := fc.GetLock(ctx)
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(404))
Expect(newLockId).To(Equal(""))
})
It("Get lock success", func() {
// assume failure happens because the target file doesn't exists
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("GetLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.GetLockResponse{
Status: status.NewOK(ctx),
Lock: &providerv1beta1.Lock{
LockId: "zzz999",
Type: providerv1beta1.LockType_LOCK_TYPE_WRITE,
},
}, nil)
newLockId, err := fc.GetLock(ctx)
Expect(err).To(Succeed())
Expect(newLockId).To(Equal("zzz999"))
})
})
Describe("Lock", func() {
Describe("Lock", func() {
It("No valid context", func() {
ctx := context.Background()
newLockId, err := fc.Lock(ctx, "newLock", "")
Expect(err).To(HaveOccurred())
Expect(newLockId).To(Equal(""))
})
It("Empty lockId", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
newLockId, err := fc.Lock(ctx, "", "")
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(400))
Expect(newLockId).To(Equal(""))
})
It("Set lock failed", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
targetErr := errors.New("Something went wrong")
gatewayClient.On("SetLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.SetLockResponse{
Status: status.NewInternal(ctx, "Something failed"),
}, targetErr)
newLockId, err := fc.Lock(ctx, "abcdef123", "")
Expect(err).To(HaveOccurred())
Expect(err).To(Equal(targetErr))
Expect(newLockId).To(Equal(""))
})
It("Set lock success", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("SetLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.SetLockResponse{
Status: status.NewOK(ctx),
}, nil)
newLockId, err := fc.Lock(ctx, "abcdef123", "")
Expect(err).To(Succeed())
Expect(newLockId).To(Equal(""))
})
It("Set lock mismatches error getting lock", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("SetLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.SetLockResponse{
Status: status.NewFailedPrecondition(ctx, nil, "lock mismatch"),
}, nil)
targetErr := errors.New("Something went wrong getting the lock")
gatewayClient.On("GetLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.GetLockResponse{
Status: status.NewInternal(ctx, "lock mismatch"),
}, targetErr)
newLockId, err := fc.Lock(ctx, "abcdef123", "")
Expect(err).To(HaveOccurred())
Expect(err).To(Equal(targetErr))
Expect(newLockId).To(Equal(""))
})
It("Set lock mismatches", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("SetLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.SetLockResponse{
Status: status.NewFailedPrecondition(ctx, nil, "lock mismatch"),
}, nil)
gatewayClient.On("GetLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.GetLockResponse{
Status: status.NewOK(ctx),
Lock: &providerv1beta1.Lock{
LockId: "zzz999",
Type: providerv1beta1.LockType_LOCK_TYPE_WRITE,
},
}, nil)
newLockId, err := fc.Lock(ctx, "abcdef123", "")
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(409))
Expect(newLockId).To(Equal("zzz999"))
})
It("Set lock mismatches but get lock matches", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("SetLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.SetLockResponse{
Status: status.NewFailedPrecondition(ctx, nil, "lock mismatch"),
}, nil)
gatewayClient.On("GetLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.GetLockResponse{
Status: status.NewOK(ctx),
Lock: &providerv1beta1.Lock{
LockId: "abcdef123",
Type: providerv1beta1.LockType_LOCK_TYPE_WRITE,
},
}, nil)
newLockId, err := fc.Lock(ctx, "abcdef123", "")
Expect(err).To(Succeed())
Expect(newLockId).To(Equal("abcdef123"))
})
It("Set lock mismatches but get lock doesn't return lockId", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("SetLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.SetLockResponse{
Status: status.NewFailedPrecondition(ctx, nil, "lock mismatch"),
}, nil)
gatewayClient.On("GetLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.GetLockResponse{
Status: status.NewOK(ctx),
}, nil)
newLockId, err := fc.Lock(ctx, "abcdef123", "")
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(500))
Expect(newLockId).To(Equal(""))
})
It("File not found", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("SetLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.SetLockResponse{
Status: status.NewNotFound(ctx, "file not found"),
}, nil)
newLockId, err := fc.Lock(ctx, "abcdef123", "")
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(404))
Expect(newLockId).To(Equal(""))
})
It("Default error handling (insufficient storage)", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("SetLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.SetLockResponse{
Status: status.NewInsufficientStorage(ctx, nil, "file too big"),
}, nil)
newLockId, err := fc.Lock(ctx, "abcdef123", "")
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(500))
Expect(newLockId).To(Equal(""))
})
})
Describe("Unlock and relock", func() {
It("No valid context", func() {
ctx := context.Background()
newLockId, err := fc.Lock(ctx, "newLock", "oldLock")
Expect(err).To(HaveOccurred())
Expect(newLockId).To(Equal(""))
})
It("Empty lockId", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
newLockId, err := fc.Lock(ctx, "", "oldLock")
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(400))
Expect(newLockId).To(Equal(""))
})
It("Refresh lock failed", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
targetErr := errors.New("Something went wrong")
gatewayClient.On("RefreshLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.RefreshLockResponse{
Status: status.NewInternal(ctx, "Something failed"),
}, targetErr)
newLockId, err := fc.Lock(ctx, "abcdef123", "oldLock")
Expect(err).To(HaveOccurred())
Expect(err).To(Equal(targetErr))
Expect(newLockId).To(Equal(""))
})
It("Refresh lock success", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("RefreshLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.RefreshLockResponse{
Status: status.NewOK(ctx),
}, nil)
newLockId, err := fc.Lock(ctx, "abcdef123", "oldLock")
Expect(err).To(Succeed())
Expect(newLockId).To(Equal(""))
})
It("Refresh lock mismatches error getting lock", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("RefreshLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.RefreshLockResponse{
Status: status.NewConflict(ctx, nil, "lock mismatch"),
}, nil)
targetErr := errors.New("Something went wrong getting the lock")
gatewayClient.On("GetLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.GetLockResponse{
Status: status.NewInternal(ctx, "lock mismatch"),
}, targetErr)
newLockId, err := fc.Lock(ctx, "abcdef123", "112233")
Expect(err).To(HaveOccurred())
Expect(err).To(Equal(targetErr))
Expect(newLockId).To(Equal(""))
})
It("Refresh lock mismatches", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("RefreshLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.RefreshLockResponse{
Status: status.NewConflict(ctx, nil, "lock mismatch"),
}, nil)
gatewayClient.On("GetLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.GetLockResponse{
Status: status.NewOK(ctx),
Lock: &providerv1beta1.Lock{
LockId: "zzz999",
Type: providerv1beta1.LockType_LOCK_TYPE_WRITE,
},
}, nil)
newLockId, err := fc.Lock(ctx, "abcdef123", "112233")
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(409))
Expect(newLockId).To(Equal("zzz999"))
})
It("Refresh lock mismatches but get lock matches", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("RefreshLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.RefreshLockResponse{
Status: status.NewConflict(ctx, nil, "lock mismatch"),
}, nil)
gatewayClient.On("GetLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.GetLockResponse{
Status: status.NewOK(ctx),
Lock: &providerv1beta1.Lock{
LockId: "abcdef123",
Type: providerv1beta1.LockType_LOCK_TYPE_WRITE,
},
}, nil)
newLockId, err := fc.Lock(ctx, "abcdef123", "112233")
Expect(err).To(Succeed())
Expect(newLockId).To(Equal("abcdef123"))
})
It("Refresh lock mismatches but get lock doesn't return lockId", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("RefreshLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.RefreshLockResponse{
Status: status.NewConflict(ctx, nil, "lock mismatch"),
}, nil)
gatewayClient.On("GetLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.GetLockResponse{
Status: status.NewOK(ctx),
}, nil)
newLockId, err := fc.Lock(ctx, "abcdef123", "112233")
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(500))
Expect(newLockId).To(Equal(""))
})
It("File not found", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("RefreshLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.RefreshLockResponse{
Status: status.NewNotFound(ctx, "file not found"),
}, nil)
newLockId, err := fc.Lock(ctx, "abcdef123", "112233")
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(404))
Expect(newLockId).To(Equal(""))
})
It("Default error handling (insufficient storage)", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("RefreshLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.RefreshLockResponse{
Status: status.NewInsufficientStorage(ctx, nil, "file too big"),
}, nil)
newLockId, err := fc.Lock(ctx, "abcdef123", "112233")
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(500))
Expect(newLockId).To(Equal(""))
})
})
})
Describe("RefreshLock", func() {
It("No valid context", func() {
ctx := context.Background()
newLockId, err := fc.RefreshLock(ctx, "newLock")
Expect(err).To(HaveOccurred())
Expect(newLockId).To(Equal(""))
})
It("Empty lockId", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
newLockId, err := fc.RefreshLock(ctx, "")
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(400))
Expect(newLockId).To(Equal(""))
})
It("Refresh lock fails", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
targetErr := errors.New("Something went wrong")
gatewayClient.On("RefreshLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.RefreshLockResponse{
Status: status.NewConflict(ctx, nil, "lock mismatch"),
}, targetErr)
newLockId, err := fc.RefreshLock(ctx, "abcdef123")
Expect(err).To(HaveOccurred())
Expect(err).To(Equal(targetErr))
Expect(newLockId).To(Equal(""))
})
It("Refresh lock success", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("RefreshLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.RefreshLockResponse{
Status: status.NewOK(ctx),
}, nil)
newLockId, err := fc.RefreshLock(ctx, "abcdef123")
Expect(err).To(Succeed())
Expect(newLockId).To(Equal(""))
})
It("Refresh lock file not found", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("RefreshLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.RefreshLockResponse{
Status: status.NewNotFound(ctx, "file not found"),
}, nil)
newLockId, err := fc.RefreshLock(ctx, "abcdef123")
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(404))
Expect(newLockId).To(Equal(""))
})
It("Refresh lock mismatch and get lock fails", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("RefreshLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.RefreshLockResponse{
Status: status.NewConflict(ctx, nil, "lock mismatch"),
}, nil)
targetErr := errors.New("Something went wrong")
gatewayClient.On("GetLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.GetLockResponse{
Status: status.NewConflict(ctx, nil, "lock mismatch"),
}, targetErr)
newLockId, err := fc.RefreshLock(ctx, "abcdef123")
Expect(err).To(HaveOccurred())
Expect(err).To(Equal(targetErr))
Expect(newLockId).To(Equal(""))
})
It("Refresh lock mismatch and get lock status not ok", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("RefreshLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.RefreshLockResponse{
Status: status.NewConflict(ctx, nil, "lock mismatch"),
}, nil)
gatewayClient.On("GetLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.GetLockResponse{
Status: status.NewInternal(ctx, "lock mismatch"),
}, nil)
newLockId, err := fc.RefreshLock(ctx, "abcdef123")
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(500))
Expect(newLockId).To(Equal(""))
})
It("Refresh lock mismatch and no lock", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("RefreshLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.RefreshLockResponse{
Status: status.NewConflict(ctx, nil, "lock mismatch"),
}, nil)
gatewayClient.On("GetLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.GetLockResponse{
Status: status.NewOK(ctx),
}, nil)
newLockId, err := fc.RefreshLock(ctx, "abcdef123")
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(409))
Expect(newLockId).To(Equal(""))
})
It("Refresh lock mismatch", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("RefreshLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.RefreshLockResponse{
Status: status.NewConflict(ctx, nil, "lock mismatch"),
}, nil)
gatewayClient.On("GetLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.GetLockResponse{
Status: status.NewOK(ctx),
Lock: &providerv1beta1.Lock{
LockId: "zzz999",
Type: providerv1beta1.LockType_LOCK_TYPE_WRITE,
},
}, nil)
newLockId, err := fc.RefreshLock(ctx, "abcdef123")
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(409))
Expect(newLockId).To(Equal("zzz999"))
})
It("Default error handling (insufficient storage)", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("RefreshLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.RefreshLockResponse{
Status: status.NewInsufficientStorage(ctx, nil, "file too big"),
}, nil)
newLockId, err := fc.RefreshLock(ctx, "abcdef123")
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(500))
Expect(newLockId).To(Equal(""))
})
})
Describe("Unlock", func() {
It("No valid context", func() {
ctx := context.Background()
newLockId, err := fc.UnLock(ctx, "newLock")
Expect(err).To(HaveOccurred())
Expect(newLockId).To(Equal(""))
})
It("Empty lockId", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
newLockId, err := fc.UnLock(ctx, "")
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(400))
Expect(newLockId).To(Equal(""))
})
It("Unlock fails", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
targetErr := errors.New("Something went wrong")
gatewayClient.On("Unlock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.UnlockResponse{
Status: status.NewInternal(ctx, "something failed"),
}, targetErr)
newLockId, err := fc.UnLock(ctx, "abcdef123")
Expect(err).To(HaveOccurred())
Expect(err).To(Equal(targetErr))
Expect(newLockId).To(Equal(""))
})
It("Unlock success", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("Unlock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.UnlockResponse{
Status: status.NewOK(ctx),
}, nil)
newLockId, err := fc.UnLock(ctx, "abcdef123")
Expect(err).To(Succeed())
Expect(newLockId).To(Equal(""))
})
It("Unlock file isn't locked", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("Unlock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.UnlockResponse{
Status: status.NewConflict(ctx, nil, "lock mismatch"),
}, nil)
newLockId, err := fc.UnLock(ctx, "abcdef123")
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(409))
Expect(newLockId).To(Equal(""))
})
It("Unlock mismatch get lock fails", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("Unlock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.UnlockResponse{
Status: status.NewLocked(ctx, "lock mismatch"),
}, nil)
targetErr := errors.New("Something went wrong")
gatewayClient.On("GetLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.GetLockResponse{
Status: status.NewInternal(ctx, "something failed"),
}, targetErr)
newLockId, err := fc.UnLock(ctx, "abcdef123")
Expect(err).To(HaveOccurred())
Expect(err).To(Equal(targetErr))
Expect(newLockId).To(Equal(""))
})
It("Unlock mismatch get lock status not ok", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("Unlock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.UnlockResponse{
Status: status.NewLocked(ctx, "lock mismatch"),
}, nil)
gatewayClient.On("GetLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.GetLockResponse{
Status: status.NewInternal(ctx, "something failed"),
}, nil)
newLockId, err := fc.UnLock(ctx, "abcdef123")
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(500))
Expect(newLockId).To(Equal(""))
})
It("Unlock mismatch get lock doesn't return lock", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("Unlock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.UnlockResponse{
Status: status.NewLocked(ctx, "lock mismatch"),
}, nil)
gatewayClient.On("GetLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.GetLockResponse{
Status: status.NewOK(ctx),
}, nil)
newLockId, err := fc.UnLock(ctx, "abcdef123")
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(409))
Expect(newLockId).To(Equal(""))
})
It("Unlock mismatch", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("Unlock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.UnlockResponse{
Status: status.NewLocked(ctx, "lock mismatch"),
}, nil)
gatewayClient.On("GetLock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.GetLockResponse{
Status: status.NewOK(ctx),
Lock: &providerv1beta1.Lock{
LockId: "zzz999",
Type: providerv1beta1.LockType_LOCK_TYPE_WRITE,
},
}, nil)
newLockId, err := fc.UnLock(ctx, "abcdef123")
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(409))
Expect(newLockId).To(Equal("zzz999"))
})
It("Default error handling (insufficient storage)", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("Unlock", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.UnlockResponse{
Status: status.NewInsufficientStorage(ctx, nil, "file too big"),
}, nil)
newLockId, err := fc.UnLock(ctx, "abcdef123")
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(500))
Expect(newLockId).To(Equal(""))
})
})
Describe("CheckFileInfo", func() {
It("No valid context", func() {
ctx := context.Background()
newFileInfo, err := fc.CheckFileInfo(ctx)
Expect(err).To(HaveOccurred())
Expect(newFileInfo).To(Equal(connector.FileInfo{}))
})
It("Stat fails", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
targetErr := errors.New("Something went wrong")
gatewayClient.On("Stat", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.StatResponse{
Status: status.NewInternal(ctx, "something failed"),
}, targetErr)
newFileInfo, err := fc.CheckFileInfo(ctx)
Expect(err).To(HaveOccurred())
Expect(err).To(Equal(targetErr))
Expect(newFileInfo).To(Equal(connector.FileInfo{}))
})
It("Stat fails status not ok", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("Stat", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.StatResponse{
Status: status.NewInternal(ctx, "something failed"),
}, nil)
newFileInfo, err := fc.CheckFileInfo(ctx)
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(500))
Expect(newFileInfo).To(Equal(connector.FileInfo{}))
})
It("Stat success", func() {
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("Stat", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.StatResponse{
Status: status.NewOK(ctx),
Info: &providerv1beta1.ResourceInfo{
Owner: &userv1beta1.UserId{
Idp: "customIdp",
OpaqueId: "aabbcc",
Type: userv1beta1.UserType_USER_TYPE_PRIMARY,
},
Size: uint64(998877),
Mtime: &typesv1beta1.Timestamp{
Seconds: uint64(16273849),
},
Path: "/path/to/test.txt",
// Other properties aren't used for now.
},
}, nil)
expectedFileInfo := connector.FileInfo{
OwnerId: "61616262636340637573746f6d496470", // hex of aabbcc@customIdp
Size: int64(998877),
Version: "16273849.0",
BaseFileName: "test.txt",
BreadcrumbDocName: "test.txt",
UserCanNotWriteRelative: true,
HostViewUrl: "http://test.ex.prv/view",
HostEditUrl: "http://test.ex.prv/edit",
EnableOwnerTermination: false,
SupportsExtendedLockLength: true,
SupportsGetLock: true,
SupportsLocks: true,
SupportsUpdate: true,
UserCanWrite: true,
UserId: "6f7061717565496440696e6d656d6f7279", // hex of opaqueId@inmemory
UserFriendlyName: "Pet Shaft",
}
newFileInfo, err := fc.CheckFileInfo(ctx)
Expect(err).To(Succeed())
Expect(newFileInfo).To(Equal(expectedFileInfo))
})
It("Stat success guests", func() {
// add user's opaque to include public-share-role
wopiCtx.User.Opaque = &typesv1beta1.Opaque{
Map: map[string]*typesv1beta1.OpaqueEntry{
"public-share-role": &typesv1beta1.OpaqueEntry{
Decoder: "plain",
Value: []byte("viewer"),
},
},
}
// change view mode to view only
wopiCtx.ViewMode = appproviderv1beta1.ViewMode_VIEW_MODE_VIEW_ONLY
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
gatewayClient.On("Stat", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.StatResponse{
Status: status.NewOK(ctx),
Info: &providerv1beta1.ResourceInfo{
Owner: &userv1beta1.UserId{
Idp: "customIdp",
OpaqueId: "aabbcc",
Type: userv1beta1.UserType_USER_TYPE_PRIMARY,
},
Size: uint64(998877),
Mtime: &typesv1beta1.Timestamp{
Seconds: uint64(16273849),
},
Path: "/path/to/test.txt",
// Other properties aren't used for now.
},
}, nil)
expectedFileInfo := connector.FileInfo{
OwnerId: "61616262636340637573746f6d496470", // hex of aabbcc@customIdp
Size: int64(998877),
Version: "16273849.0",
BaseFileName: "test.txt",
BreadcrumbDocName: "test.txt",
UserCanNotWriteRelative: true,
HostViewUrl: "http://test.ex.prv/view",
HostEditUrl: "http://test.ex.prv/edit",
EnableOwnerTermination: false,
SupportsExtendedLockLength: true,
SupportsGetLock: true,
SupportsLocks: true,
DisableExport: true,
DisableCopy: true,
DisablePrint: true,
IsAnonymousUser: true,
UserId: "guest-zzz000",
UserFriendlyName: "guest zzz000",
}
newFileInfo, err := fc.CheckFileInfo(ctx)
// UserId and UserFriendlyName have random Ids generated which are impossible to guess
// Check both separately
Expect(newFileInfo.UserId).To(HavePrefix(hex.EncodeToString([]byte("guest-"))))
Expect(newFileInfo.UserFriendlyName).To(HavePrefix("Guest "))
// overwrite UserId and UserFriendlyName here for easier matching
newFileInfo.UserId = "guest-zzz000"
newFileInfo.UserFriendlyName = "guest zzz000"
Expect(err).To(Succeed())
Expect(newFileInfo).To(Equal(expectedFileInfo))
})
})
})

View File

@@ -0,0 +1,124 @@
package helpers_test
import (
"net/http"
"net/http/httptest"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/owncloud/ocis/v2/ocis-pkg/log"
"github.com/owncloud/ocis/v2/services/collaboration/pkg/config"
"github.com/owncloud/ocis/v2/services/collaboration/pkg/helpers"
)
var _ = Describe("Discovery", func() {
var (
discoveryContent1 string
srv *httptest.Server
)
BeforeEach(func() {
discoveryContent1 = `
<?xml version="1.0" encoding="utf-8"?>
<wopi-discovery>
<net-zone name="external-http">
<app name="Word" favIconUrl="https://test.server.prv/web-apps/apps/documenteditor/main/resources/img/favicon.ico">
<action name="view" ext="pdf" urlsrc="https://test.server.prv/hosting/wopi/word/view?&amp;&lt;rs=DC_LLCC&amp;&gt;&lt;dchat=DISABLE_CHAT&amp;&gt;&lt;embed=EMBEDDED&amp;&gt;&lt;fs=FULLSCREEN&amp;&gt;&lt;hid=HOST_SESSION_ID&amp;&gt;&lt;rec=RECORDING&amp;&gt;&lt;sc=SESSION_CONTEXT&amp;&gt;&lt;thm=THEME_ID&amp;&gt;&lt;ui=UI_LLCC&amp;&gt;&lt;wopisrc=WOPI_SOURCE&amp;&gt;&amp;"/>
<action name="embedview" ext="pdf" urlsrc="https://test.server.prv/hosting/wopi/word/view?embed=1&amp;&lt;rs=DC_LLCC&amp;&gt;&lt;dchat=DISABLE_CHAT&amp;&gt;&lt;embed=EMBEDDED&amp;&gt;&lt;fs=FULLSCREEN&amp;&gt;&lt;hid=HOST_SESSION_ID&amp;&gt;&lt;rec=RECORDING&amp;&gt;&lt;sc=SESSION_CONTEXT&amp;&gt;&lt;thm=THEME_ID&amp;&gt;&lt;ui=UI_LLCC&amp;&gt;&lt;wopisrc=WOPI_SOURCE&amp;&gt;&amp;"/>
<action name="view" ext="djvu" urlsrc="https://test.server.prv/hosting/wopi/word/view?&amp;&lt;rs=DC_LLCC&amp;&gt;&lt;dchat=DISABLE_CHAT&amp;&gt;&lt;embed=EMBEDDED&amp;&gt;&lt;fs=FULLSCREEN&amp;&gt;&lt;hid=HOST_SESSION_ID&amp;&gt;&lt;rec=RECORDING&amp;&gt;&lt;sc=SESSION_CONTEXT&amp;&gt;&lt;thm=THEME_ID&amp;&gt;&lt;ui=UI_LLCC&amp;&gt;&lt;wopisrc=WOPI_SOURCE&amp;&gt;&amp;"/>
<action name="embedview" ext="djvu" urlsrc="https://test.server.prv/hosting/wopi/word/view?embed=1&amp;&lt;rs=DC_LLCC&amp;&gt;&lt;dchat=DISABLE_CHAT&amp;&gt;&lt;embed=EMBEDDED&amp;&gt;&lt;fs=FULLSCREEN&amp;&gt;&lt;hid=HOST_SESSION_ID&amp;&gt;&lt;rec=RECORDING&amp;&gt;&lt;sc=SESSION_CONTEXT&amp;&gt;&lt;thm=THEME_ID&amp;&gt;&lt;ui=UI_LLCC&amp;&gt;&lt;wopisrc=WOPI_SOURCE&amp;&gt;&amp;"/>
<action name="view" ext="docx" urlsrc="https://test.server.prv/hosting/wopi/word/view?&amp;&lt;rs=DC_LLCC&amp;&gt;&lt;dchat=DISABLE_CHAT&amp;&gt;&lt;embed=EMBEDDED&amp;&gt;&lt;fs=FULLSCREEN&amp;&gt;&lt;hid=HOST_SESSION_ID&amp;&gt;&lt;rec=RECORDING&amp;&gt;&lt;sc=SESSION_CONTEXT&amp;&gt;&lt;thm=THEME_ID&amp;&gt;&lt;ui=UI_LLCC&amp;&gt;&lt;wopisrc=WOPI_SOURCE&amp;&gt;&amp;"/>
<action name="embedview" ext="docx" urlsrc="https://test.server.prv/hosting/wopi/word/view?embed=1&amp;&lt;rs=DC_LLCC&amp;&gt;&lt;dchat=DISABLE_CHAT&amp;&gt;&lt;embed=EMBEDDED&amp;&gt;&lt;fs=FULLSCREEN&amp;&gt;&lt;hid=HOST_SESSION_ID&amp;&gt;&lt;rec=RECORDING&amp;&gt;&lt;sc=SESSION_CONTEXT&amp;&gt;&lt;thm=THEME_ID&amp;&gt;&lt;ui=UI_LLCC&amp;&gt;&lt;wopisrc=WOPI_SOURCE&amp;&gt;&amp;"/>
<action name="editnew" ext="docx" requires="locks,update" urlsrc="https://test.server.prv/hosting/wopi/word/edit?&amp;&lt;rs=DC_LLCC&amp;&gt;&lt;dchat=DISABLE_CHAT&amp;&gt;&lt;embed=EMBEDDED&amp;&gt;&lt;fs=FULLSCREEN&amp;&gt;&lt;hid=HOST_SESSION_ID&amp;&gt;&lt;rec=RECORDING&amp;&gt;&lt;sc=SESSION_CONTEXT&amp;&gt;&lt;thm=THEME_ID&amp;&gt;&lt;ui=UI_LLCC&amp;&gt;&lt;wopisrc=WOPI_SOURCE&amp;&gt;&amp;"/>
<action name="edit" ext="docx" default="true" requires="locks,update" urlsrc="https://test.server.prv/hosting/wopi/word/edit?&amp;&lt;rs=DC_LLCC&amp;&gt;&lt;dchat=DISABLE_CHAT&amp;&gt;&lt;embed=EMBEDDED&amp;&gt;&lt;fs=FULLSCREEN&amp;&gt;&lt;hid=HOST_SESSION_ID&amp;&gt;&lt;rec=RECORDING&amp;&gt;&lt;sc=SESSION_CONTEXT&amp;&gt;&lt;thm=THEME_ID&amp;&gt;&lt;ui=UI_LLCC&amp;&gt;&lt;wopisrc=WOPI_SOURCE&amp;&gt;&amp;"/>
</app>
<app name="Excel" favIconUrl="https://test.server.prv/web-apps/apps/spreadsheeteditor/main/resources/img/favicon.ico">
<action name="view" ext="xls" urlsrc="https://test.server.prv/hosting/wopi/cell/view?&amp;&lt;rs=DC_LLCC&amp;&gt;&lt;dchat=DISABLE_CHAT&amp;&gt;&lt;embed=EMBEDDED&amp;&gt;&lt;fs=FULLSCREEN&amp;&gt;&lt;hid=HOST_SESSION_ID&amp;&gt;&lt;rec=RECORDING&amp;&gt;&lt;sc=SESSION_CONTEXT&amp;&gt;&lt;thm=THEME_ID&amp;&gt;&lt;ui=UI_LLCC&amp;&gt;&lt;wopisrc=WOPI_SOURCE&amp;&gt;&amp;"/>
<action name="embedview" ext="xls" urlsrc="https://test.server.prv/hosting/wopi/cell/view?embed=1&amp;&lt;rs=DC_LLCC&amp;&gt;&lt;dchat=DISABLE_CHAT&amp;&gt;&lt;embed=EMBEDDED&amp;&gt;&lt;fs=FULLSCREEN&amp;&gt;&lt;hid=HOST_SESSION_ID&amp;&gt;&lt;rec=RECORDING&amp;&gt;&lt;sc=SESSION_CONTEXT&amp;&gt;&lt;thm=THEME_ID&amp;&gt;&lt;ui=UI_LLCC&amp;&gt;&lt;wopisrc=WOPI_SOURCE&amp;&gt;&amp;"/>
<action name="convert" ext="xls" targetext="xlsx" requires="update" urlsrc="https://test.server.prv/hosting/wopi/convert-and-edit/xls/xlsx?&amp;&lt;rs=DC_LLCC&amp;&gt;&lt;dchat=DISABLE_CHAT&amp;&gt;&lt;embed=EMBEDDED&amp;&gt;&lt;fs=FULLSCREEN&amp;&gt;&lt;hid=HOST_SESSION_ID&amp;&gt;&lt;rec=RECORDING&amp;&gt;&lt;sc=SESSION_CONTEXT&amp;&gt;&lt;thm=THEME_ID&amp;&gt;&lt;ui=UI_LLCC&amp;&gt;&lt;wopisrc=WOPI_SOURCE&amp;&gt;&amp;"/>
<action name="view" ext="xlsb" urlsrc="https://test.server.prv/hosting/wopi/cell/view?&amp;&lt;rs=DC_LLCC&amp;&gt;&lt;dchat=DISABLE_CHAT&amp;&gt;&lt;embed=EMBEDDED&amp;&gt;&lt;fs=FULLSCREEN&amp;&gt;&lt;hid=HOST_SESSION_ID&amp;&gt;&lt;rec=RECORDING&amp;&gt;&lt;sc=SESSION_CONTEXT&amp;&gt;&lt;thm=THEME_ID&amp;&gt;&lt;ui=UI_LLCC&amp;&gt;&lt;wopisrc=WOPI_SOURCE&amp;&gt;&amp;"/>
<action name="embedview" ext="xlsb" urlsrc="https://test.server.prv/hosting/wopi/cell/view?embed=1&amp;&lt;rs=DC_LLCC&amp;&gt;&lt;dchat=DISABLE_CHAT&amp;&gt;&lt;embed=EMBEDDED&amp;&gt;&lt;fs=FULLSCREEN&amp;&gt;&lt;hid=HOST_SESSION_ID&amp;&gt;&lt;rec=RECORDING&amp;&gt;&lt;sc=SESSION_CONTEXT&amp;&gt;&lt;thm=THEME_ID&amp;&gt;&lt;ui=UI_LLCC&amp;&gt;&lt;wopisrc=WOPI_SOURCE&amp;&gt;&amp;"/>
<action name="convert" ext="xlsb" targetext="xlsx" requires="update" urlsrc="https://test.server.prv/hosting/wopi/convert-and-edit/xlsb/xlsx?&amp;&lt;rs=DC_LLCC&amp;&gt;&lt;dchat=DISABLE_CHAT&amp;&gt;&lt;embed=EMBEDDED&amp;&gt;&lt;fs=FULLSCREEN&amp;&gt;&lt;hid=HOST_SESSION_ID&amp;&gt;&lt;rec=RECORDING&amp;&gt;&lt;sc=SESSION_CONTEXT&amp;&gt;&lt;thm=THEME_ID&amp;&gt;&lt;ui=UI_LLCC&amp;&gt;&lt;wopisrc=WOPI_SOURCE&amp;&gt;&amp;"/>
</app>
<app name="application/vnd.oasis.opendocument.presentation">
<action name="edit" ext="" default="true" requires="locks,update" urlsrc="https://test.server.prv/hosting/wopi/slide/edit?&amp;&lt;rs=DC_LLCC&amp;&gt;&lt;dchat=DISABLE_CHAT&amp;&gt;&lt;embed=EMBEDDED&amp;&gt;&lt;fs=FULLSCREEN&amp;&gt;&lt;hid=HOST_SESSION_ID&amp;&gt;&lt;rec=RECORDING&amp;&gt;&lt;sc=SESSION_CONTEXT&amp;&gt;&lt;thm=THEME_ID&amp;&gt;&lt;ui=UI_LLCC&amp;&gt;&lt;wopisrc=WOPI_SOURCE&amp;&gt;&amp;"/>
</app>
</net-zone>
<proof-key oldvalue="BgIAAACkAABSU0ExAAgAAAEAAQD/NVqekFNi8X3p6Bvdlaxm0GGuggW5kKfVEQzPGuOkGVrz6DrOMNR+k7Pq8tONY+1NHgS6Z+v3959em78qclVDuQX77Tkml0xMHAQHN4sAHF9iQJS8gOBUKSVKaHD7Z8YXch6F212YSUSc8QphpDSHWVShU7rcUeLQsd/0pkflh5+um4YKEZhm4Mou3vstp5p12NeffyK1WFZF7q4jB7jclAslYKQsP82YY3DcRwu5Tl/+W0ifVcXze0mI7v1reJ12pKn8ifRiq+0q5oJST3TRSrvmjLg9Gt3ozhVIt2HUi3La7Qh40YOAUXm0g/hUq2BepeOp1C7WSvaOFHXe6Hqq" oldmodulus="qnro3nUUjvZK1i7UqeOlXmCrVPiDtHlRgIPReAjt2nKL1GG3SBXO6N0aPbiM5rtK0XRPUoLmKu2rYvSJ/Kmkdp14a/3uiEl788VVn0hb/l9OuQtH3HBjmM0/LKRgJQuU3LgHI67uRVZYtSJ/n9fYdZqnLfveLsrgZpgRCoabrp+H5Uem9N+x0OJR3LpToVRZhzSkYQrxnERJmF3bhR5yF8Zn+3BoSiUpVOCAvJRAYl8cAIs3BwQcTEyXJjnt+wW5Q1VyKr+bXp/39+tnugQeTe1jjdPy6rOTftQwzjro81oZpOMazwwR1aeQuQWCrmHQZqyV3Rvo6X3xYlOQnlo1/w==" oldexponent="AQAB" value="BgIAAACkAABSU0ExAAgAAAEAAQD/NVqekFNi8X3p6Bvdlaxm0GGuggW5kKfVEQzPGuOkGVrz6DrOMNR+k7Pq8tONY+1NHgS6Z+v3959em78qclVDuQX77Tkml0xMHAQHN4sAHF9iQJS8gOBUKSVKaHD7Z8YXch6F212YSUSc8QphpDSHWVShU7rcUeLQsd/0pkflh5+um4YKEZhm4Mou3vstp5p12NeffyK1WFZF7q4jB7jclAslYKQsP82YY3DcRwu5Tl/+W0ifVcXze0mI7v1reJ12pKn8ifRiq+0q5oJST3TRSrvmjLg9Gt3ozhVIt2HUi3La7Qh40YOAUXm0g/hUq2BepeOp1C7WSvaOFHXe6Hqq" modulus="qnro3nUUjvZK1i7UqeOlXmCrVPiDtHlRgIPReAjt2nKL1GG3SBXO6N0aPbiM5rtK0XRPUoLmKu2rYvSJ/Kmkdp14a/3uiEl788VVn0hb/l9OuQtH3HBjmM0/LKRgJQuU3LgHI67uRVZYtSJ/n9fYdZqnLfveLsrgZpgRCoabrp+H5Uem9N+x0OJR3LpToVRZhzSkYQrxnERJmF3bhR5yF8Zn+3BoSiUpVOCAvJRAYl8cAIs3BwQcTEyXJjnt+wW5Q1VyKr+bXp/39+tnugQeTe1jjdPy6rOTftQwzjro81oZpOMazwwR1aeQuQWCrmHQZqyV3Rvo6X3xYlOQnlo1/w==" exponent="AQAB"/>
</wopi-discovery>
`
srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
switch req.URL.Path {
case "/bad/hosting/discovery":
w.WriteHeader(500)
case "/good/hosting/discovery":
w.Write([]byte(discoveryContent1))
case "/wrongformat/hosting/discovery":
w.Write([]byte("Text that <can't> be XML /form<atted/"))
}
}))
})
AfterEach(func() {
srv.Close()
})
Describe("GetAppURLs", func() {
It("Good discovery URL", func() {
cfg := &config.Config{
WopiApp: config.WopiApp{
Addr: srv.URL + "/good",
Insecure: true,
},
}
logger := log.NopLogger()
appUrls, err := helpers.GetAppURLs(cfg, logger)
expectedAppUrls := map[string]map[string]string{
"view": map[string]string{
".pdf": "https://test.server.prv/hosting/wopi/word/view",
".djvu": "https://test.server.prv/hosting/wopi/word/view",
".docx": "https://test.server.prv/hosting/wopi/word/view",
".xls": "https://test.server.prv/hosting/wopi/cell/view",
".xlsb": "https://test.server.prv/hosting/wopi/cell/view",
},
"edit": map[string]string{
".docx": "https://test.server.prv/hosting/wopi/word/edit",
},
}
Expect(err).To(Succeed())
Expect(appUrls).To(Equal(expectedAppUrls))
})
It("Wrong discovery URL", func() {
cfg := &config.Config{
WopiApp: config.WopiApp{
Addr: srv.URL + "/bad",
Insecure: true,
},
}
logger := log.NopLogger()
appUrls, err := helpers.GetAppURLs(cfg, logger)
Expect(err).To(HaveOccurred())
Expect(appUrls).To(BeNil())
})
It("Not XML formatted", func() {
cfg := &config.Config{
WopiApp: config.WopiApp{
Addr: srv.URL + "/wrongformat",
Insecure: true,
},
}
logger := log.NopLogger()
appUrls, err := helpers.GetAppURLs(cfg, logger)
Expect(err).To(HaveOccurred())
Expect(appUrls).To(BeNil())
})
})
})

View File

@@ -0,0 +1,13 @@
package helpers_test
import (
"testing"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
func TestGraph(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Helpers Suite")
}

View File

@@ -86,9 +86,20 @@ func WopiContextAuthMiddleware(jwtSecret string, next http.Handler) http.Handler
})
}
// Extract a WopiContext from the context if possible. An error will be
// returned if there is no WopiContext
func WopiContextFromCtx(ctx context.Context) (WopiContext, error) {
if wopiContext, ok := ctx.Value(wopiContextKey).(WopiContext); ok {
return wopiContext, nil
}
return WopiContext{}, errors.New("no wopi context found")
}
// Set a WopiContext in the context. A new context will be returned with the
// add WopiContext inside. Note that the old one won't have the WopiContext set.
//
// This method is used for testing. The WopiContextAuthMiddleware should be
// used instead in order to provide a valid WopiContext
func WopiContextToCtx(ctx context.Context, wopiContext WopiContext) context.Context {
return context.WithValue(ctx, wopiContextKey, wopiContext)
}