Repository: spf13/afero (go)

Issue:
Incorrect WriteAt implementation for mem.File
To reproduce: https://play.golang.org/p/-mM7CBvnFVl

I'd put `fmt.Println(f.fileData.data)` to `(*mem.File).WriteAt`, so I got
```
[0 0 0 0 0 1 2 3 4 5]
[1 2 3 4 5 1 2 3 4 5]
[1 2 3 4 5 1 2 3 4 5 1 2 3 4 5]
[0 0 0 0 0 1 2 3 4 5]
[0 0 0 0 0 1 2 3 4 5]
```
Seems like `Write` does not copy old data if reallocation needed.


Pull request description:
Fix incorrect (*mem.File).WriteAt
Fixes #286.

Patch:
diff --git a/mem/file.go b/mem/file.go
index 290369a..5a20730 100644
--- a/mem/file.go
+++ b/mem/file.go
@@ -267,7 +267,7 @@ func (f *File) Write(b []byte) (n int, err error) {
 		tail = f.fileData.data[n+int(cur):]
 	}
 	if diff > 0 {
-		f.fileData.data = append(bytes.Repeat([]byte{00}, int(diff)), b...)
+		f.fileData.data = append(f.fileData.data, append(bytes.Repeat([]byte{00}, int(diff)), b...)...)
 		f.fileData.data = append(f.fileData.data, tail...)
 	} else {
 		f.fileData.data = append(f.fileData.data[:cur], b...)


Test patch:
diff --git a/mem/file_test.go b/mem/file_test.go
index 22af970..998a5d0 100644
--- a/mem/file_test.go
+++ b/mem/file_test.go
@@ -95,6 +95,57 @@ func TestFileDataModeRace(t *testing.T) {
 	}
 }
 
+// See https://github.com/spf13/afero/issues/286.
+func TestFileWriteAt(t *testing.T) {
+	t.Parallel()
+
+	data := CreateFile("abc.txt")
+	f := NewFileHandle(data)
+
+	testData := []byte{1, 2, 3, 4, 5}
+	offset := len(testData)
+
+	// 5 zeros + testdata
+	_, err := f.WriteAt(testData, int64(offset))
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// 2 * testdata
+	_, err = f.WriteAt(testData, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// 3 * testdata
+	_, err = f.WriteAt(testData, int64(offset*2))
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// 3 * testdata + 5 zeros + testdata
+	_, err = f.WriteAt(testData, int64(offset*4))
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// 5 * testdata
+	_, err = f.WriteAt(testData, int64(offset*3))
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	err = f.Close()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	expected := bytes.Repeat(testData, 5)
+	if !bytes.Equal(expected, data.data) {
+		t.Fatalf("expected: %v, got: %v", expected, data.data)
+	}
+}
+
 func TestFileDataIsDirRace(t *testing.T) {
 	t.Parallel()