github.com/Serizao/go-winio@v0.0.0-20230906082528-f02f7f4ad6e8/backup_test.go (about) 1 //go:build windows 2 // +build windows 3 4 package winio 5 6 import ( 7 "io" 8 "os" 9 "testing" 10 11 "golang.org/x/sys/windows" 12 ) 13 14 var testFileName string 15 16 func TestMain(m *testing.M) { 17 f, err := os.CreateTemp("", "tmp") 18 if err != nil { 19 panic(err) 20 } 21 testFileName = f.Name() 22 f.Close() 23 defer os.Remove(testFileName) 24 os.Exit(m.Run()) 25 } 26 27 func makeTestFile(makeADS bool) error { 28 os.Remove(testFileName) 29 f, err := os.Create(testFileName) 30 if err != nil { 31 return err 32 } 33 defer f.Close() 34 _, err = f.Write([]byte("testing 1 2 3\n")) 35 if err != nil { 36 return err 37 } 38 if makeADS { 39 a, err := os.Create(testFileName + ":ads.txt") 40 if err != nil { 41 return err 42 } 43 defer a.Close() 44 _, err = a.Write([]byte("alternate data stream\n")) 45 if err != nil { 46 return err 47 } 48 } 49 return nil 50 } 51 52 func TestBackupRead(t *testing.T) { 53 err := makeTestFile(true) 54 if err != nil { 55 t.Fatal(err) 56 } 57 58 f, err := os.Open(testFileName) 59 if err != nil { 60 t.Fatal(err) 61 } 62 defer f.Close() 63 r := NewBackupFileReader(f, false) 64 defer r.Close() 65 b, err := io.ReadAll(r) 66 if err != nil { 67 t.Fatal(err) 68 } 69 if len(b) == 0 { 70 t.Fatal("no data") 71 } 72 } 73 74 func TestBackupStreamRead(t *testing.T) { 75 err := makeTestFile(true) 76 if err != nil { 77 t.Fatal(err) 78 } 79 80 f, err := os.Open(testFileName) 81 if err != nil { 82 t.Fatal(err) 83 } 84 defer f.Close() 85 r := NewBackupFileReader(f, false) 86 defer r.Close() 87 88 br := NewBackupStreamReader(r) 89 gotData := false 90 gotAltData := false 91 for { 92 hdr, err := br.Next() 93 if err == io.EOF { //nolint:errorlint 94 break 95 } 96 if err != nil { 97 t.Fatal(err) 98 } 99 100 switch hdr.Id { 101 case BackupData: 102 if gotData { 103 t.Fatal("duplicate data") 104 } 105 if hdr.Name != "" { 106 t.Fatalf("unexpected name %s", hdr.Name) 107 } 108 b, err := io.ReadAll(br) 109 if err != nil { 110 t.Fatal(err) 111 } 112 if string(b) != "testing 1 2 3\n" { 113 t.Fatalf("incorrect data %v", b) 114 } 115 gotData = true 116 case BackupAlternateData: 117 if gotAltData { 118 t.Fatal("duplicate alt data") 119 } 120 if hdr.Name != ":ads.txt:$DATA" { 121 t.Fatalf("incorrect name %s", hdr.Name) 122 } 123 b, err := io.ReadAll(br) 124 if err != nil { 125 t.Fatal(err) 126 } 127 if string(b) != "alternate data stream\n" { 128 t.Fatalf("incorrect data %v", b) 129 } 130 gotAltData = true 131 default: 132 t.Fatalf("unknown stream ID %d", hdr.Id) 133 } 134 } 135 if !gotData || !gotAltData { 136 t.Fatal("missing stream") 137 } 138 } 139 140 func TestBackupStreamWrite(t *testing.T) { 141 f, err := os.Create(testFileName) 142 if err != nil { 143 t.Fatal(err) 144 } 145 defer f.Close() 146 w := NewBackupFileWriter(f, false) 147 defer w.Close() 148 149 data := "testing 1 2 3\n" 150 altData := "alternate stream\n" 151 152 br := NewBackupStreamWriter(w) 153 err = br.WriteHeader(&BackupHeader{Id: BackupData, Size: int64(len(data))}) 154 if err != nil { 155 t.Fatal(err) 156 } 157 n, err := br.Write([]byte(data)) 158 if err != nil { 159 t.Fatal(err) 160 } 161 if n != len(data) { 162 t.Fatal("short write") 163 } 164 165 err = br.WriteHeader(&BackupHeader{Id: BackupAlternateData, Size: int64(len(altData)), Name: ":ads.txt:$DATA"}) 166 if err != nil { 167 t.Fatal(err) 168 } 169 n, err = br.Write([]byte(altData)) 170 if err != nil { 171 t.Fatal(err) 172 } 173 if n != len(altData) { 174 t.Fatal("short write") 175 } 176 177 f.Close() 178 179 b, err := os.ReadFile(testFileName) 180 if err != nil { 181 t.Fatal(err) 182 } 183 if string(b) != data { 184 t.Fatalf("wrong data %v", b) 185 } 186 187 b, err = os.ReadFile(testFileName + ":ads.txt") 188 if err != nil { 189 t.Fatal(err) 190 } 191 if string(b) != altData { 192 t.Fatalf("wrong data %v", b) 193 } 194 } 195 196 func makeSparseFile() error { 197 os.Remove(testFileName) 198 f, err := os.Create(testFileName) 199 if err != nil { 200 return err 201 } 202 defer f.Close() 203 204 err = windows.DeviceIoControl(windows.Handle(f.Fd()), windows.FSCTL_SET_SPARSE, nil, 0, nil, 0, nil, nil) 205 if err != nil { 206 return err 207 } 208 209 _, err = f.Write([]byte("testing 1 2 3\n")) 210 if err != nil { 211 return err 212 } 213 214 _, err = f.Seek(1000000, 0) 215 if err != nil { 216 return err 217 } 218 219 _, err = f.Write([]byte("more data later\n")) 220 if err != nil { 221 return err 222 } 223 224 return nil 225 } 226 227 func TestBackupSparseFile(t *testing.T) { 228 err := makeSparseFile() 229 if err != nil { 230 t.Fatal(err) 231 } 232 233 f, err := os.Open(testFileName) 234 if err != nil { 235 t.Fatal(err) 236 } 237 defer f.Close() 238 r := NewBackupFileReader(f, false) 239 defer r.Close() 240 241 br := NewBackupStreamReader(r) 242 for { 243 hdr, err := br.Next() 244 if err == io.EOF { //nolint:errorlint 245 break 246 } 247 if err != nil { 248 t.Fatal(err) 249 } 250 251 t.Log(hdr) 252 } 253 }