//go:build unix package mmap_test import ( "bytes" "os" "path/filepath" "testing" "lindenii.org/go/furgit/internal/mmap" ) // makeTempFileWithContents creates one file with content and opens it for reading. func makeTempFileWithContents(t *testing.T, content []byte) *os.File { t.Helper() path := filepath.Join(t.TempDir(), "data") err := os.WriteFile(path, content, 0o600) if err != nil { t.Fatalf("WriteFile: %v", err) } file, err := os.Open(path) //nolint:gosec if err != nil { t.Fatalf("Open: %v", err) } t.Cleanup(func() { _ = file.Close() }) return file } // makeLargeTempFileLongerThanPage creates and opens one file // whose content repeats seed // until it spans more than one OS page. func makeLargeTempFileLongerThanPage(t *testing.T, seed []byte) (*os.File, []byte) { t.Helper() content := bytes.Repeat(seed, os.Getpagesize()/len(seed)+2) return makeTempFileWithContents(t, content), content } func TestOpenData(t *testing.T) { t.Parallel() file, content := makeLargeTempFileLongerThanPage(t, []byte("mapped bytes\n")) mapping, err := mmap.Open(file) if err != nil { t.Fatalf("Open: %v", err) } // The mapping must survive closing the originating file. err = file.Close() if err != nil { t.Fatalf("file Close: %v", err) } if !bytes.Equal(mapping.Data(), content) { t.Fatalf("Data mismatch") } err = mapping.Close() if err != nil { t.Fatalf("Close: %v", err) } } func TestOpenEmpty(t *testing.T) { t.Parallel() file := makeTempFileWithContents(t, nil) mapping, err := mmap.Open(file) if err != nil { t.Fatalf("Open: %v", err) } if len(mapping.Data()) != 0 { t.Fatalf("Data = %d bytes, want empty", len(mapping.Data())) } err = mapping.Close() if err != nil { t.Fatalf("Close: %v", err) } } func TestCloseIdempotent(t *testing.T) { t.Parallel() file, _ := makeLargeTempFileLongerThanPage(t, []byte("once")) mapping, err := mmap.Open(file) if err != nil { t.Fatalf("Open: %v", err) } err = mapping.Close() if err != nil { t.Fatalf("first Close: %v", err) } err = mapping.Close() if err != nil { t.Fatalf("second Close: %v", err) } }