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