浏览代码

webdav: fix memFile.Write to advance the file position.

Change-Id: Ic0c1ac9c328360fb591e040c3c837b2ca6234193
Nigel Tao 11 年之前
父节点
当前提交
d8b496d92d
共有 2 个文件被更改,包括 204 次插入0 次删除
  1. 1 0
      webdav/file.go
  2. 203 0
      webdav/file_test.go

+ 1 - 0
webdav/file.go

@@ -413,6 +413,7 @@ func (f *memFile) Write(p []byte) (int, error) {
 		f.n.data = d
 	}
 	copy(f.n.data[f.pos:], p)
+	f.pos = epos
 	f.n.modTime = time.Now()
 	return len(p), nil
 }

+ 203 - 0
webdav/file_test.go

@@ -6,7 +6,11 @@ package webdav
 
 import (
 	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
 	"path/filepath"
+	"strconv"
 	"strings"
 	"testing"
 )
@@ -193,3 +197,202 @@ func TestWalk(t *testing.T) {
 		}
 	}
 }
+
+func TestMemFile(t *testing.T) {
+	testCases := []string{
+		"wantData ",
+		"wantSize 0",
+		"write abc",
+		"wantData abc",
+		"write de",
+		"wantData abcde",
+		"wantSize 5",
+		"write 5*x",
+		"write 4*y+2*z",
+		"write 3*st",
+		"wantData abcdexxxxxyyyyzzststst",
+		"wantSize 22",
+		"seek set 4 want 4",
+		"write EFG",
+		"wantData abcdEFGxxxyyyyzzststst",
+		"wantSize 22",
+		"seek set 2 want 2",
+		"read cdEF",
+		"read Gx",
+		"seek cur 0 want 8",
+		"seek cur 2 want 10",
+		"seek cur -1 want 9",
+		"write J",
+		"wantData abcdEFGxxJyyyyzzststst",
+		"wantSize 22",
+		"seek cur -4 want 6",
+		"write ghijk",
+		"wantData abcdEFghijkyyyzzststst",
+		"wantSize 22",
+		"read yyyz",
+		"seek cur 0 want 15",
+		"write ",
+		"seek cur 0 want 15",
+		"read ",
+		"seek cur 0 want 15",
+		"seek end -3 want 19",
+		"write ZZ",
+		"wantData abcdEFghijkyyyzzstsZZt",
+		"wantSize 22",
+		"write 4*A",
+		"wantData abcdEFghijkyyyzzstsZZAAAA",
+		"wantSize 25",
+		"seek end 0 want 25",
+		"seek end -5 want 20",
+		"read Z+4*A",
+		"write 5*B",
+		"wantData abcdEFghijkyyyzzstsZZAAAABBBBB",
+		"wantSize 30",
+		"seek end 10 want 40",
+		"write C",
+		"wantData abcdEFghijkyyyzzstsZZAAAABBBBB..........C",
+		"wantSize 41",
+		"seek set 43 want 43",
+		"write D",
+		"wantData abcdEFghijkyyyzzstsZZAAAABBBBB..........C..D",
+		"wantSize 44",
+		"seek set 0 want 0",
+		"write 5*123456789_",
+		"wantData 123456789_123456789_123456789_123456789_123456789_",
+		"wantSize 50",
+		"seek cur 0 want 50",
+		"seek cur -99 want err",
+	}
+
+	const filename = "/foo"
+	fs := NewMemFS()
+	f, err := fs.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
+	if err != nil {
+		t.Fatalf("OpenFile: %v", err)
+	}
+	defer f.Close()
+
+	for i, tc := range testCases {
+		j := strings.IndexByte(tc, ' ')
+		if j < 0 {
+			t.Fatalf("test case #%d %q: invalid command", i, tc)
+		}
+		op, arg := tc[:j], tc[j+1:]
+
+		// Expand an arg like "3*a+2*b" to "aaabb".
+		parts := strings.Split(arg, "+")
+		for j, part := range parts {
+			if k := strings.IndexByte(part, '*'); k >= 0 {
+				repeatCount, repeatStr := part[:k], part[k+1:]
+				n, err := strconv.Atoi(repeatCount)
+				if err != nil {
+					t.Fatalf("test case #%d %q: invalid repeat count %q", i, tc, repeatCount)
+				}
+				parts[j] = strings.Repeat(repeatStr, n)
+			}
+		}
+		arg = strings.Join(parts, "")
+
+		switch op {
+		default:
+			t.Fatalf("test case #%d %q: invalid operation %q", i, tc, op)
+
+		case "read":
+			buf := make([]byte, len(arg))
+			if _, err := io.ReadFull(f, buf); err != nil {
+				t.Fatalf("test case #%d %q: ReadFull: %v", i, tc, err)
+			}
+			if got := string(buf); got != arg {
+				t.Fatalf("test case #%d %q:\ngot  %q\nwant %q", i, tc, got, arg)
+			}
+
+		case "seek":
+			parts := strings.Split(arg, " ")
+			if len(parts) != 4 {
+				t.Fatalf("test case #%d %q: invalid seek", i, tc)
+			}
+
+			whence := 0
+			switch parts[0] {
+			default:
+				t.Fatalf("test case #%d %q: invalid seek whence", i, tc)
+			case "set":
+				whence = os.SEEK_SET
+			case "cur":
+				whence = os.SEEK_CUR
+			case "end":
+				whence = os.SEEK_END
+			}
+			offset, err := strconv.Atoi(parts[1])
+			if err != nil {
+				t.Fatalf("test case #%d %q: invalid offset %q", i, tc, parts[1])
+			}
+
+			if parts[2] != "want" {
+				t.Fatalf("test case #%d %q: invalid seek", i, tc)
+			}
+			if parts[3] == "err" {
+				_, err := f.Seek(int64(offset), whence)
+				if err == nil {
+					t.Fatalf("test case #%d %q: Seek returned nil error, want non-nil", i, tc)
+				}
+			} else {
+				got, err := f.Seek(int64(offset), whence)
+				if err != nil {
+					t.Fatalf("test case #%d %q: Seek: %v", i, tc, err)
+				}
+				want, err := strconv.Atoi(parts[3])
+				if err != nil {
+					t.Fatalf("test case #%d %q: invalid want %q", i, tc, parts[3])
+				}
+				if got != int64(want) {
+					t.Fatalf("test case #%d %q: got %d, want %d", i, tc, got, want)
+				}
+			}
+
+		case "write":
+			n, err := f.Write([]byte(arg))
+			if err != nil {
+				t.Fatalf("test case #%d %q: write: %v", i, tc, err)
+			}
+			if n != len(arg) {
+				t.Fatalf("test case #%d %q: write returned %d bytes, want %d", i, tc, n, len(arg))
+			}
+
+		case "wantData":
+			g, err := fs.OpenFile(filename, os.O_RDONLY, 0666)
+			if err != nil {
+				t.Fatalf("test case #%d %q: OpenFile: %v", i, tc, err)
+			}
+			gotBytes, err := ioutil.ReadAll(g)
+			if err != nil {
+				t.Fatalf("test case #%d %q: ReadAll: %v", i, tc, err)
+			}
+			for i, c := range gotBytes {
+				if c == '\x00' {
+					gotBytes[i] = '.'
+				}
+			}
+			got := string(gotBytes)
+			if got != arg {
+				t.Fatalf("test case #%d %q:\ngot  %q\nwant %q", i, tc, got, arg)
+			}
+			if err := g.Close(); err != nil {
+				t.Fatalf("test case #%d %q: Close: %v", i, tc, err)
+			}
+
+		case "wantSize":
+			n, err := strconv.Atoi(arg)
+			if err != nil {
+				t.Fatalf("test case #%d %q: invalid size %q", i, tc, arg)
+			}
+			fi, err := fs.Stat(filename)
+			if err != nil {
+				t.Fatalf("test case #%d %q: Stat: %v", i, tc, err)
+			}
+			if got, want := fi.Size(), int64(n); got != want {
+				t.Fatalf("test case #%d %q: got %d, want %d", i, tc, got, want)
+			}
+		}
+	}
+}