summaryrefslogtreecommitdiff
path: root/client_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'client_test.go')
-rw-r--r--client_test.go129
1 files changed, 129 insertions, 0 deletions
diff --git a/client_test.go b/client_test.go
index af890f0..8c447e1 100644
--- a/client_test.go
+++ b/client_test.go
@@ -42,12 +42,17 @@ type testService struct {
deleteFileRequests chan *zwdaemonv1.DeleteFileRequest
deleteFileErr error
+ moveFileRequests chan *zwdaemonv1.MoveFileRequest
+ moveFileErr error
+ copyFileRequests chan *zwdaemonv1.CopyFileRequest
+ copyFileErr error
compactCalls chan struct{}
compactErr error
getFile func(*zwdaemonv1.GetFileRequest, grpc.ServerStreamingServer[zwdaemonv1.GetFileResponse]) error
getFileRange func(*zwdaemonv1.GetFileRangeRequest, grpc.ServerStreamingServer[zwdaemonv1.GetFileRangeResponse]) error
addFile func(grpc.ClientStreamingServer[zwdaemonv1.AddFileRequest, zwdaemonv1.AddFileResponse]) error
+ replaceFile func(grpc.ClientStreamingServer[zwdaemonv1.ReplaceFileRequest, zwdaemonv1.ReplaceFileResponse]) error
}
func (s *testService) GetServerInfo(
@@ -120,6 +125,26 @@ func (s *testService) Compact(
return &zwdaemonv1.CompactResponse{}, s.compactErr
}
+func (s *testService) MoveFile(
+ _ context.Context,
+ request *zwdaemonv1.MoveFileRequest,
+) (*zwdaemonv1.MoveFileResponse, error) {
+ if s.moveFileRequests != nil {
+ s.moveFileRequests <- request
+ }
+ return &zwdaemonv1.MoveFileResponse{}, s.moveFileErr
+}
+
+func (s *testService) CopyFile(
+ _ context.Context,
+ request *zwdaemonv1.CopyFileRequest,
+) (*zwdaemonv1.CopyFileResponse, error) {
+ if s.copyFileRequests != nil {
+ s.copyFileRequests <- request
+ }
+ return &zwdaemonv1.CopyFileResponse{}, s.copyFileErr
+}
+
func (s *testService) GetFile(
request *zwdaemonv1.GetFileRequest,
stream grpc.ServerStreamingServer[zwdaemonv1.GetFileResponse],
@@ -149,6 +174,15 @@ func (s *testService) AddFile(
return s.addFile(stream)
}
+func (s *testService) ReplaceFile(
+ stream grpc.ClientStreamingServer[zwdaemonv1.ReplaceFileRequest, zwdaemonv1.ReplaceFileResponse],
+) error {
+ if s.replaceFile == nil {
+ return stream.SendAndClose(&zwdaemonv1.ReplaceFileResponse{})
+ }
+ return s.replaceFile(stream)
+}
+
func startTestServer(t *testing.T, service *testService) string {
t.Helper()
@@ -536,6 +570,32 @@ func TestDeleteFileMapsRequestAndStructuredError(t *testing.T) {
}
}
+func TestMoveAndCopyFileMapRequests(t *testing.T) {
+ service := &testService{
+ moveFileRequests: make(chan *zwdaemonv1.MoveFileRequest, 1),
+ copyFileRequests: make(chan *zwdaemonv1.CopyFileRequest, 1),
+ }
+ client := startConnectedTestClient(t, service)
+ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+ defer cancel()
+
+ if err := client.MoveFile(ctx, "source.txt", "renamed.txt"); err != nil {
+ t.Fatalf("MoveFile() error = %v", err)
+ }
+ moveRequest := <-service.moveFileRequests
+ if moveRequest.GetSourcePath() != "source.txt" || moveRequest.GetDestinationPath() != "renamed.txt" {
+ t.Errorf("MoveFile request = %#v", moveRequest)
+ }
+
+ if err := client.CopyFile(ctx, "source.txt", "copy.txt"); err != nil {
+ t.Fatalf("CopyFile() error = %v", err)
+ }
+ copyRequest := <-service.copyFileRequests
+ if copyRequest.GetSourcePath() != "source.txt" || copyRequest.GetDestinationPath() != "copy.txt" {
+ t.Errorf("CopyFile request = %#v", copyRequest)
+ }
+}
+
func TestConvertRPCErrorAcceptsNil(t *testing.T) {
if err := convertRPCError(nil); err != nil {
t.Fatalf("convertRPCError(nil) = %v", err)
@@ -827,6 +887,41 @@ func TestAddFileProcessesDataReturnedWithEOF(t *testing.T) {
}
}
+func TestReplaceFileSendsHeaderAndChunks(t *testing.T) {
+ received := make(chan receivedReplaceUpload, 1)
+ service := &testService{
+ replaceFile: func(
+ stream grpc.ClientStreamingServer[zwdaemonv1.ReplaceFileRequest, zwdaemonv1.ReplaceFileResponse],
+ ) error {
+ upload, err := receiveReplaceUpload(stream)
+ if err != nil {
+ return err
+ }
+ received <- upload
+ return stream.SendAndClose(&zwdaemonv1.ReplaceFileResponse{})
+ },
+ }
+ client := startConnectedTestClient(t, service)
+ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+ defer cancel()
+
+ contents := []byte("replacement contents")
+ if err := client.ReplaceFile(ctx, "existing.bin", bytes.NewReader(contents), uint64(len(contents))); err != nil {
+ t.Fatalf("ReplaceFile() error = %v", err)
+ }
+
+ upload := <-received
+ if upload.header.GetLogicalPath() != "existing.bin" {
+ t.Errorf("logical path = %q", upload.header.GetLogicalPath())
+ }
+ if upload.header.GetSourceLen() != uint64(len(contents)) {
+ t.Errorf("source length = %d", upload.header.GetSourceLen())
+ }
+ if !bytes.Equal(upload.contents, contents) {
+ t.Errorf("replacement contents differ")
+ }
+}
+
func TestAddFileReturnsLengthRejectionFromCloseAndRecv(t *testing.T) {
serverStatus, err := status.New(codes.InvalidArgument, "declared length does not match source").WithDetails(
&zwdaemonv1.ZwErrorDetail{
@@ -977,6 +1072,40 @@ func receiveUpload(
}
}
+type receivedReplaceUpload struct {
+ header *zwdaemonv1.ReplaceFileHeader
+ contents []byte
+}
+
+func receiveReplaceUpload(
+ stream grpc.ClientStreamingServer[zwdaemonv1.ReplaceFileRequest, zwdaemonv1.ReplaceFileResponse],
+) (receivedReplaceUpload, error) {
+ first, err := stream.Recv()
+ if err != nil {
+ return receivedReplaceUpload{}, err
+ }
+ header := first.GetHeader()
+ if header == nil {
+ return receivedReplaceUpload{}, status.Error(codes.InvalidArgument, "first replacement message is not a header")
+ }
+
+ upload := receivedReplaceUpload{header: header}
+ for {
+ request, err := stream.Recv()
+ if err == io.EOF {
+ return upload, nil
+ }
+ if err != nil {
+ return upload, err
+ }
+ payload, ok := request.GetPayload().(*zwdaemonv1.ReplaceFileRequest_Chunk)
+ if !ok {
+ return upload, status.Error(codes.InvalidArgument, "replacement message after header is not a chunk")
+ }
+ upload.contents = append(upload.contents, payload.Chunk...)
+ }
+}
+
type dataAndEOFReader struct {
data []byte
done bool