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