github.com/10XDev/rclone@v1.52.3-0.20200626220027-16af9ab76b2a/vfs/vfstest/write_unix.go (about)

     1  // +build linux darwin freebsd
     2  
     3  package vfstest
     4  
     5  import (
     6  	"runtime"
     7  	"testing"
     8  
     9  	"github.com/rclone/rclone/vfs/vfscommon"
    10  	"github.com/stretchr/testify/assert"
    11  	"golang.org/x/sys/unix"
    12  )
    13  
    14  // TestWriteFileDoubleClose tests double close on write
    15  func TestWriteFileDoubleClose(t *testing.T) {
    16  	run.skipIfVFS(t)
    17  	run.skipIfNoFUSE(t)
    18  	if runtime.GOOS == "darwin" {
    19  		t.Skip("Skipping test on OSX")
    20  	}
    21  
    22  	out, err := osCreate(run.path("testdoubleclose"))
    23  	assert.NoError(t, err)
    24  	fd := out.Fd()
    25  
    26  	fd1, err := unix.Dup(int(fd))
    27  	assert.NoError(t, err)
    28  
    29  	fd2, err := unix.Dup(int(fd))
    30  	assert.NoError(t, err)
    31  
    32  	// close one of the dups - should produce no error
    33  	err = unix.Close(fd1)
    34  	assert.NoError(t, err)
    35  
    36  	// write to the file
    37  	buf := []byte("hello")
    38  	n, err := out.Write(buf)
    39  	assert.NoError(t, err)
    40  	assert.Equal(t, 5, n)
    41  
    42  	// close it
    43  	err = out.Close()
    44  	assert.NoError(t, err)
    45  
    46  	// write to the other dup
    47  	_, err = unix.Write(fd2, buf)
    48  	if run.vfs.Opt.CacheMode < vfscommon.CacheModeWrites {
    49  		// produces an error if cache mode < writes
    50  		assert.Error(t, err, "input/output error")
    51  	} else {
    52  		// otherwise does not produce an error
    53  		assert.NoError(t, err)
    54  	}
    55  
    56  	// close the dup - should not produce an error
    57  	err = unix.Close(fd2)
    58  	assert.NoError(t, err)
    59  
    60  	run.waitForWriters()
    61  	run.rm(t, "testdoubleclose")
    62  }
    63  
    64  // writeTestDup performs the platform-specific implementation of the dup() unix
    65  func writeTestDup(oldfd uintptr) (uintptr, error) {
    66  	newfd, err := unix.Dup(int(oldfd))
    67  	return uintptr(newfd), err
    68  }