Source file src/cmd/link/internal/ld/fallocate_test.go

     1  // Copyright 2020 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build darwin || (freebsd && go1.21) || linux
     6  
     7  package ld
     8  
     9  import (
    10  	"errors"
    11  	"os"
    12  	"path/filepath"
    13  	"syscall"
    14  	"testing"
    15  )
    16  
    17  func TestFallocate(t *testing.T) {
    18  	dir := t.TempDir()
    19  	filename := filepath.Join(dir, "a.out")
    20  	out := NewOutBuf(nil)
    21  	err := out.Open(filename)
    22  	if err != nil {
    23  		t.Fatalf("Open file failed: %v", err)
    24  	}
    25  	defer out.Close()
    26  
    27  	// Try fallocate first.
    28  	for {
    29  		err = out.fallocate(1 << 10)
    30  		if errors.Is(err, errors.ErrUnsupported) || err == errNoFallocate { // The underlying file system may not support fallocate
    31  			t.Skip("fallocate is not supported")
    32  		}
    33  		if err == syscall.EINTR {
    34  			continue // try again
    35  		}
    36  		if err != nil {
    37  			t.Fatalf("fallocate failed: %v", err)
    38  		}
    39  		break
    40  	}
    41  
    42  	// Mmap 1 MiB initially, and grow to 2 and 3 MiB.
    43  	// Check if the file size and disk usage is expected.
    44  	for _, sz := range []int64{1 << 20, 2 << 20, 3 << 20} {
    45  		err = out.Mmap(uint64(sz))
    46  		if err != nil {
    47  			t.Fatalf("Mmap failed: %v", err)
    48  		}
    49  		stat, err := os.Stat(filename)
    50  		if err != nil {
    51  			t.Fatalf("Stat failed: %v", err)
    52  		}
    53  		if got := stat.Size(); got != sz {
    54  			t.Errorf("unexpected file size: got %d, want %d", got, sz)
    55  		}
    56  		// The number of blocks must be enough for the requested size.
    57  		// We used to require an exact match, but it appears that
    58  		// some file systems allocate a few extra blocks in some cases.
    59  		// See issue #41127.
    60  		if got, want := stat.Sys().(*syscall.Stat_t).Blocks, (sz+511)/512; got < want {
    61  			t.Errorf("unexpected disk usage: got %d blocks, want at least %d", got, want)
    62  		}
    63  		out.munmap()
    64  	}
    65  }
    66  

View as plain text