github.com/Serizao/go-winio@v0.0.0-20230906082528-f02f7f4ad6e8/fileinfo_test.go (about)

     1  //go:build windows
     2  // +build windows
     3  
     4  package winio
     5  
     6  import (
     7  	"os"
     8  	"testing"
     9  
    10  	"golang.org/x/sys/windows"
    11  )
    12  
    13  // Checks if current matches expected. Note that AllocationSize is filesystem-specific,
    14  // so we check that the current.AllocationSize is >= expected.AllocationSize.
    15  // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/5afa7f66-619c-48f3-955f-68c4ece704ae
    16  func checkFileStandardInfo(t *testing.T, current, expected *FileStandardInfo) {
    17  	t.Helper()
    18  
    19  	if current.AllocationSize < expected.AllocationSize {
    20  		t.Fatalf("FileStandardInfo unexpectedly had AllocationSize %d, expecting >=%d", current.AllocationSize, expected.AllocationSize)
    21  	}
    22  
    23  	if current.EndOfFile != expected.EndOfFile {
    24  		t.Fatalf("FileStandardInfo unexpectedly had EndOfFile %d, expecting %d", current.EndOfFile, expected.EndOfFile)
    25  	}
    26  
    27  	if current.NumberOfLinks != expected.NumberOfLinks {
    28  		t.Fatalf("FileStandardInfo unexpectedly had NumberOfLinks %d, expecting %d", current.NumberOfLinks, expected.NumberOfLinks)
    29  	}
    30  
    31  	if current.DeletePending != expected.DeletePending {
    32  		if current.DeletePending {
    33  			t.Fatalf("FileStandardInfo unexpectedly DeletePending")
    34  		} else {
    35  			t.Fatalf("FileStandardInfo unexpectedly not DeletePending")
    36  		}
    37  	}
    38  
    39  	if current.Directory != expected.Directory {
    40  		if current.Directory {
    41  			t.Fatalf("FileStandardInfo unexpectedly Directory")
    42  		} else {
    43  			t.Fatalf("FileStandardInfo unexpectedly not Directory")
    44  		}
    45  	}
    46  }
    47  
    48  func TestGetFileStandardInfo_File(t *testing.T) {
    49  	f, err := os.CreateTemp("", "tst")
    50  	if err != nil {
    51  		t.Fatal(err)
    52  	}
    53  	defer f.Close()
    54  	defer os.Remove(f.Name())
    55  
    56  	expectedFileInfo := &FileStandardInfo{
    57  		AllocationSize: 0,
    58  		EndOfFile:      0,
    59  		NumberOfLinks:  1,
    60  		DeletePending:  false,
    61  		Directory:      false,
    62  	}
    63  
    64  	info, err := GetFileStandardInfo(f)
    65  	if err != nil {
    66  		t.Fatal(err)
    67  	}
    68  	checkFileStandardInfo(t, info, expectedFileInfo)
    69  
    70  	bytesWritten, err := f.Write([]byte("0123456789"))
    71  	if err != nil {
    72  		t.Fatal(err)
    73  	}
    74  
    75  	expectedFileInfo.EndOfFile = int64(bytesWritten)
    76  	expectedFileInfo.AllocationSize = int64(bytesWritten)
    77  
    78  	info, err = GetFileStandardInfo(f)
    79  	if err != nil {
    80  		t.Fatal(err)
    81  	}
    82  	checkFileStandardInfo(t, info, expectedFileInfo)
    83  
    84  	linkName := f.Name() + ".link"
    85  
    86  	if err = os.Link(f.Name(), linkName); err != nil {
    87  		t.Fatal(err)
    88  	}
    89  	defer os.Remove(linkName)
    90  
    91  	expectedFileInfo.NumberOfLinks = 2
    92  
    93  	info, err = GetFileStandardInfo(f)
    94  	if err != nil {
    95  		t.Fatal(err)
    96  	}
    97  	checkFileStandardInfo(t, info, expectedFileInfo)
    98  
    99  	os.Remove(linkName)
   100  
   101  	expectedFileInfo.NumberOfLinks = 1
   102  
   103  	info, err = GetFileStandardInfo(f)
   104  	if err != nil {
   105  		t.Fatal(err)
   106  	}
   107  	checkFileStandardInfo(t, info, expectedFileInfo)
   108  }
   109  
   110  func TestGetFileStandardInfo_Directory(t *testing.T) {
   111  	tempDir := t.TempDir()
   112  	// os.Open returns the Search Handle, not the Directory Handle
   113  	// See https://github.com/golang/go/issues/13738
   114  	f, err := OpenForBackup(tempDir, windows.GENERIC_READ, 0, windows.OPEN_EXISTING)
   115  	if err != nil {
   116  		t.Fatal(err)
   117  	}
   118  	defer f.Close()
   119  
   120  	expectedFileInfo := &FileStandardInfo{
   121  		AllocationSize: 0,
   122  		EndOfFile:      0,
   123  		NumberOfLinks:  1,
   124  		DeletePending:  false,
   125  		Directory:      true,
   126  	}
   127  
   128  	info, err := GetFileStandardInfo(f)
   129  	if err != nil {
   130  		t.Fatal(err)
   131  	}
   132  	checkFileStandardInfo(t, info, expectedFileInfo)
   133  }