github.com/anacrolix/torrent@v1.61.0/storage/file-io-mmap_test.go (about)

     1  package storage
     2  
     3  import (
     4  	"bytes"
     5  	"os"
     6  	"path/filepath"
     7  	"testing"
     8  
     9  	"github.com/go-quicktest/qt"
    10  )
    11  
    12  // Note this is AI slop with some modifications. Test if writes to mmap without sync or flush are
    13  // detected by a subsequent seek data. It would appear they are since the mmap is created from the
    14  // file descriptor used for the seek, and probably because we're in the same process so MAP_SHARED
    15  // kicks in.
    16  func TestFileIoImplementationsSeekDataDetection(t *testing.T) {
    17  	testData := []byte{0x42}
    18  	writeOffset := int64(1234567) // Large enough for sparse files to kick in.
    19  	const fileSize = 12345678
    20  
    21  	implementations := []struct {
    22  		name   string
    23  		fileIo fileIo
    24  	}{
    25  		{"classic", classicFileIo{}},
    26  		{"mmap", &mmapFileIo{}},
    27  	}
    28  
    29  	for _, impl := range implementations {
    30  		t.Run(impl.name, func(t *testing.T) {
    31  			// Create temporary directory and file
    32  			tempDir := t.TempDir()
    33  			t.Logf("tempDir: %s", tempDir)
    34  			testFile := filepath.Join(tempDir, "test.dat")
    35  
    36  			// Create empty file
    37  			f, err := os.Create(testFile)
    38  			qt.Assert(t, qt.IsNil(err))
    39  			f.Close()
    40  
    41  			// Open for write and write a byte without flushing
    42  			writer, err := impl.fileIo.openForWrite(testFile, fileSize)
    43  			qt.Assert(t, qt.IsNil(err))
    44  
    45  			_, err = writer.WriteAt(testData, writeOffset)
    46  			qt.Assert(t, qt.IsNil(err))
    47  
    48  			// Close writer (but note: we didn't call flush)
    49  			err = writer.Close()
    50  			qt.Assert(t, qt.IsNil(err))
    51  
    52  			// Open for read and test seekData detection
    53  			reader, err := impl.fileIo.openForRead(testFile)
    54  			qt.Assert(t, qt.IsNil(err))
    55  			defer reader.Close()
    56  
    57  			// Use seekDataOrEof to detect data
    58  			dataPos, err := reader.seekDataOrEof(writeOffset)
    59  			qt.Assert(t, qt.IsNil(err))
    60  			qt.Assert(t, qt.Equals(dataPos, writeOffset))
    61  
    62  			var buf bytes.Buffer
    63  			written, err := reader.writeToN(&buf, 1)
    64  			qt.Assert(t, qt.IsNil(err))
    65  			qt.Assert(t, qt.Equals(written, 1))
    66  			qt.Assert(t, qt.DeepEquals(buf.Bytes(), testData))
    67  		})
    68  	}
    69  }