mirror of
https://github.com/golang/go
synced 2024-11-18 10:14:45 -07:00
os: add a test case of copying a file itself via io.Copy
Change-Id: Ib9746cb4f27625cb22620271b280d2da242b2fba Reviewed-on: https://go-review.googlesource.com/c/go/+/428437 Run-TryBot: Ian Lance Taylor <iant@google.com> Run-TryBot: Andy Pan <panjf2000@gmail.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Michael Knyszek <mknyszek@google.com> Reviewed-by: Ian Lance Taylor <iant@google.com> Auto-Submit: Ian Lance Taylor <iant@google.com>
This commit is contained in:
parent
bca17d16ca
commit
86477e507f
@ -13,6 +13,7 @@ import (
|
|||||||
. "os"
|
. "os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@ -74,6 +75,56 @@ func TestCopyFileRange(t *testing.T) {
|
|||||||
mustSeekStart(t, dst2)
|
mustSeekStart(t, dst2)
|
||||||
mustContainData(t, dst2, data) // through traditional means
|
mustContainData(t, dst2, data) // through traditional means
|
||||||
})
|
})
|
||||||
|
t.Run("CopyFileItself", func(t *testing.T) {
|
||||||
|
hook := hookCopyFileRange(t)
|
||||||
|
|
||||||
|
f, err := os.CreateTemp("", "file-readfrom-itself-test")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create tmp file: %v", err)
|
||||||
|
}
|
||||||
|
t.Cleanup(func() {
|
||||||
|
f.Close()
|
||||||
|
os.Remove(f.Name())
|
||||||
|
})
|
||||||
|
|
||||||
|
data := []byte("hello world!")
|
||||||
|
if _, err := f.Write(data); err != nil {
|
||||||
|
t.Fatalf("failed to create and feed the file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := f.Sync(); err != nil {
|
||||||
|
t.Fatalf("failed to save the file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rewind it.
|
||||||
|
if _, err := f.Seek(0, io.SeekStart); err != nil {
|
||||||
|
t.Fatalf("failed to rewind the file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read data from the file itself.
|
||||||
|
if _, err := io.Copy(f, f); err != nil {
|
||||||
|
t.Fatalf("failed to read from the file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !hook.called || hook.written != 0 || hook.handled || hook.err != nil {
|
||||||
|
t.Fatalf("poll.CopyFileRange should be called and return the EINVAL error, but got hook.called=%t, hook.err=%v", hook.called, hook.err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rewind it.
|
||||||
|
if _, err := f.Seek(0, io.SeekStart); err != nil {
|
||||||
|
t.Fatalf("failed to rewind the file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
data2, err := io.ReadAll(f)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to read from the file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// It should wind up a double of the original data.
|
||||||
|
if strings.Repeat(string(data), 2) != string(data2) {
|
||||||
|
t.Fatalf("data mismatch: %s != %s", string(data), string(data2))
|
||||||
|
}
|
||||||
|
})
|
||||||
t.Run("NotRegular", func(t *testing.T) {
|
t.Run("NotRegular", func(t *testing.T) {
|
||||||
t.Run("BothPipes", func(t *testing.T) {
|
t.Run("BothPipes", func(t *testing.T) {
|
||||||
hook := hookCopyFileRange(t)
|
hook := hookCopyFileRange(t)
|
||||||
@ -344,6 +395,10 @@ type copyFileRangeHook struct {
|
|||||||
srcfd int
|
srcfd int
|
||||||
remain int64
|
remain int64
|
||||||
|
|
||||||
|
written int64
|
||||||
|
handled bool
|
||||||
|
err error
|
||||||
|
|
||||||
original func(dst, src *poll.FD, remain int64) (int64, bool, error)
|
original func(dst, src *poll.FD, remain int64) (int64, bool, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -354,7 +409,8 @@ func (h *copyFileRangeHook) install() {
|
|||||||
h.dstfd = dst.Sysfd
|
h.dstfd = dst.Sysfd
|
||||||
h.srcfd = src.Sysfd
|
h.srcfd = src.Sysfd
|
||||||
h.remain = remain
|
h.remain = remain
|
||||||
return h.original(dst, src, remain)
|
h.written, h.handled, h.err = h.original(dst, src, remain)
|
||||||
|
return h.written, h.handled, h.err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user