1 rizwank 1.1 /*
2 * Unit test suite for cabinet.dll - FDI functions
3 *
4 * Copyright 2004 Rizwan Kassim, Dan Kegel
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include <stdlib.h>
22 rizwank 1.1
23 #ifndef STANDALONE
24 #include <wine/test.h>
25 #define ok2 ok
26 #else
27 /* To build outside Wine tree, compile with cl -DSTANDALONE -D_X86_ cabinet_fdi.c FDI.lib
28 These are only called if standalone are used, defining ok and START_TEST, which would normally be declared in winetree */
29 #include <assert.h>
30 #include <stdio.h>
31 #define START_TEST(name) main(int argc, char **argv)
32 #define ok(condition, msg) \
33 do { if(!(condition)) { \
34 fprintf(stderr,"failed at %d, msg:" msg "\n",__LINE__); \
35 exit(1); \
36 } } while(0)
37 #define ok2(condition, msg, arg) \
38 do { if(!(condition)) { \
39 fprintf(stderr,"failed at %d, msg:" msg "\n",__LINE__, arg); \
40 exit(1); \
41 } } while(0)
42 #define todo_wine
43 rizwank 1.1 #endif
44
45 #include <winerror.h>
46 #include <fdi.h>
|
47 rizwank 1.7 #include <fcntl.h>
48
|
49 rizwank 1.8 /* Do malloc and free output debug messages?
50 #define DEBUG_ALLOC
51 */
|
52 rizwank 1.7
|
53 rizwank 1.8 /* What is our "Fake" Filedescriptor? */
54 static int fakeFD = 22881;
|
55 rizwank 1.7
|
56 rizwank 1.8 /*
|
57 rizwank 2.0 This hex data is the output of makecab.exe (Windows Cabinet SDK/bin)
58 ****** IS USING THE OUTPUT OF A NON LGPL program okay ******
|
59 rizwank 1.8
60 The cab file is mirrored in the file system as simple.cab
61
62 The 'test.txt' in the cab file contains the string 'So long, and thanks for all the fish.'
63 */
|
64 rizwank 1.7 static unsigned char compressed_file[] =
65 {0x4D,0x53,0x43,0x46,0x00,0x00,0x00,0x00,0x75,0x00,
66 0x00,0x00,0x00,0x00,0x00,0x00,0x2C,0x00,0x00,0x00,
67 0x00,0x00,0x00,0x00,0x03,0x01,0x01,0x00,0x01,0x00,
68 0x00,0x00,0x39,0x30,0x00,0x00,0x45,0x00,0x00,0x00,
69 0x01,0x00,0x01,0x00,0x26,0x00,0x00,0x00,0x00,0x00,
70 0x00,0x00,0x00,0x00,0x4A,0x32,0xB2,0xBE,0x20,0x00,
71 0x74,0x65,0x73,0x74,0x2E,0x74,0x78,0x74,0x00,0x9C,
72 0x74,0xD0,0x75,0x28,0x00,0x26,0x00,0x43,0x4B,0x0B,
73 0xCE,0x57,0xC8,0xC9,0xCF,0x4B,0xD7,0x51,0x48,0xCC,
74 0x4B,0x51,0x28,0xC9,0x48,0xCC,0xCB,0x2E,0x56,0x48,
75 0xCB,0x2F,0x52,0x48,0xCC,0xC9,0x01,0x72,0x53,0x15,
76 0xD2,0x32,0x8B,0x33,0xF4,0xB8,0x00};
77 static int szcompressed_file = sizeof(compressed_file);
78
|
79 rizwank 2.0 /*
80 Multiple File Cabs are included, as cabinet.dll supports multiple file archive types.
81 The compressed file size had to be greater than 50k, cabarc restricts 'diskette spanning' to
82 archives above 50k.
83 The peculiar options were selected specifically to test cabinet.dll more throughly.
84
85 complex_lzw.cab cabarc -m LZX:16 -pr -i 32356 N complex_lzw.cab amontillado.txt lgpl.txt gpl.txt midsummer\*
86 complex_lzw2.cab cabarc -m LZX:17 -d 50000 -pr -i 32356 N complex_lzw*.cab amontillado.txt + lgpl.txt gpl.txt midsummer\*
|
87 rizwank 1.8
|
88 rizwank 2.0 complex_zip.cab cabarc -m MSZIP -pr -i 32356 N complex_lzw.cab amontillado.txt lgpl.txt gpl.txt midsummer\*
89 complex_zip2.cab cabarc -m MSZIP -d 50000 -pr -i 32356 N complex_zip*.cab amontillado.txt + lgpl.txt gpl.txt midsummer\*
|
90 rizwank 1.7
|
91 rizwank 2.0 complex_none.cab cabarc -m NONE -pr -i 32356 N complex_none.cab amontillado.txt midsummer\act1*
|
92 rizwank 1.1
|
93 rizwank 1.8 /*
94 To do in FDI: -from wine/include/fdi.h
|
95 rizwank 1.1 FDICreate
96 File Write -FNWRITE(hf, pv, cb)
97 File Seek -FNSEEK(hf,dist,seektype)
98 Error Structure
99 FDICopy
100 Notification function
101 Decryption function
102 FDIDestroy
103 */
104
|
105 rizwank 1.8 #ifndef DEBUG_ALLOC
106 FNALLOC(final_alloc) {
107 return malloc(cb);
108 }
109 FNFREE(final_free) {
110 free(pv);
111 return;
112 }
113 #else
114 FNALLOC(final_alloc) {
|
115 rizwank 1.5 printf(" FNALLOC just called with %d\n",cb);
116 return malloc(cb);
|
117 rizwank 1.3 }
|
118 rizwank 1.8 FNFREE(final_free) {
|
119 rizwank 1.5 printf(" FNFREE just called with %d\n",pv);
120 free(pv);
|
121 rizwank 1.3 return;
122 }
|
123 rizwank 1.8 #endif
124
|
125 rizwank 1.3
|
126 rizwank 1.5 /*
|
127 rizwank 1.7 Match i/o specs of _open, _read, _write, _close, and _lseek.
128 */
129
130 /*
|
131 rizwank 1.8 http://msdn.microsoft.com/library/en-us/vclib/html/_crt__open.2c_._wopen.asp
|
132 rizwank 1.7 _open I: const char *filename, int oflag, int pmode O: int (handler), -1 for err.
|
133 rizwank 1.8 DUMMY : FUNCTIONAL FAKE : FUNCTIONAL REAL : FUNCTIONAL
|
134 rizwank 1.5 */
135
|
136 rizwank 1.3 FNOPEN(dummy_open) {
|
137 rizwank 1.8 printf(" FNOPEN (dummy) just called with %d, %d, %d\n",pszFile, oflag, pmode);
|
138 rizwank 1.3 return 0;
139 }
140
|
141 rizwank 1.7 FNOPEN(fake_open) {
|
142 rizwank 1.8 printf(" FNOPEN (fake) just called with %d, %d, %d\n",pszFile, oflag, pmode);
143 printf(" Returning %d as file descriptor\n",fakeFD);
|
144 rizwank 1.7 return 12;
145 }
146
147 FNOPEN(real_open) {
148 int handler = _open(pszFile,oflag,pmode);
149 printf(" FNOPEN (real) just called with %s, %d, %d\n",pszFile, oflag, pmode);
150 printf(" FNOPEN (real) returning handler (%d)\n",handler);
151 return handler;
152 }
153
154 /*
|
155 rizwank 1.8 http://msdn.microsoft.com/library/en-us/vclib/html/_CRT__read.asp
|
156 rizwank 1.7 _read I: int fd, void *buffer, unsigned int count O: int (szBuffer)
|
157 rizwank 1.8 DUMMY : FUNCTIONAL FAKE : FUNCTIONAL, INCOMPLETE REAL : FUNCTIONAL
|
158 rizwank 1.7 */
159
|
160 rizwank 1.3 FNREAD(dummy_read) {
|
161 rizwank 1.8 printf(" FNREAD (dummy) just called with %d, %d, %d\n",hf, pv, cb);
|
162 rizwank 1.5 return 0;
|
163 rizwank 1.3 }
|
164 rizwank 1.7
|
165 rizwank 1.8 /* Doesn't keep virtual file location pointer */
|
166 rizwank 1.7 FNREAD(fake_read) {
|
167 rizwank 1.8 printf(" FNREAD (fake) just called with %d, %d, %d\n",hf, pv, cb);
168 if (hf == fakeFD) {
169 printf (" Called with fake file descriptor, populating buffer and size (%d)\n",cb);
170 memcpy (pv, compressed_file ,cb);
171 }
172 else {
173 printf (" FNREAD (fake) was called with the unknown file handler. Failed!\n",hf);
174 }
175 return cb;
|
176 rizwank 1.7 }
177
178 FNREAD(real_read) {
179 int szBuffer = _read(hf,pv,cb);
180 printf(" FNREAD (read) just called with %d, %d, %d\n",hf, pv, cb);
181 printf(" FNREAD (read) returning size (%d)\n",szBuffer);
182 return szBuffer;
183 }
184
|
185 rizwank 1.8 /*
186 http://msdn.microsoft.com/library/en-us/vclib/html/_CRT__close.asp
187 _close I: int fd O: int (0=success 1=failure)
188 DUMMY : FUNCTIONAL FAKE : FUNCTIONAL REAL : FUNCTIONAL
189 */
|
190 rizwank 1.7
|
191 rizwank 1.8 FNCLOSE(dummy_close) {
192 printf(" FNCLOSE (dummy) just called with %d - returning %d\n",hf,0);
|
193 rizwank 1.5 return 0;
|
194 rizwank 1.3 }
195
|
196 rizwank 1.8 FNCLOSE(fake_close) {
197 printf(" FNCLOSE (fake) just called with %d - returning %d\n",hf,0);
198 return 0;
199 }
|
200 rizwank 1.3
|
201 rizwank 1.8 FNCLOSE(real_close) {
202 int closevalue = _close(hf);
203 printf(" FNCLOSE (real) just called with %d - returning %d\n",hf,closevalue);
204 return closevalue;
205 }
206
207
|
208 rizwank 2.0
209
210
|
211 rizwank 1.8 FNWRITE(dummy_write) {
212 printf(" FNWRITE just called with %d, %d, %d\n",hf, pv, cb);
|
213 rizwank 1.5 return 0;
|
214 rizwank 1.3 }
|
215 rizwank 1.1
|
216 rizwank 1.3 FNSEEK(dummy_seek) {
|
217 rizwank 1.8 printf(" FNSEEK just called with %d, %d, %d\n",hf, dist, seektype);
|
218 rizwank 1.5 return 0;
|
219 rizwank 1.3 }
220
|
221 rizwank 2.0
222
|
223 rizwank 1.7 HFDI hfdi_unknown_dummy, hfdi_unknown_fake,hfdi_unknown_real;
|
224 rizwank 1.4 /* yes its global and ugly */
225
|
226 rizwank 2.0 /* Is CPU386 or Unknown more commonly used? */
|
227 rizwank 1.1
|
228 rizwank 1.4 static void TestCreate(void) {
229
230 ERF error_structure;
231
232 printf("Starting TestCreate()\n");
233
|
234 rizwank 1.7 hfdi_unknown_dummy = FDICreate(
|
235 rizwank 1.8 final_alloc,
236 final_free,
|
237 rizwank 1.5 dummy_open,
238 dummy_read,
239 dummy_write,
240 dummy_close,
241 dummy_seek,
242 cpuUNKNOWN,
243 &error_structure
244 );
|
245 rizwank 1.7 ok(hfdi_unknown_dummy != NULL,"FDICreate (CPU = unknown) (functions=dummy) failed!\n");
246
247 hfdi_unknown_fake = FDICreate(
|
248 rizwank 1.8 final_alloc,
249 final_free,
|
250 rizwank 1.7 fake_open,
251 fake_read,
252 dummy_write,
253 dummy_close,
254 dummy_seek,
255 cpuUNKNOWN,
256 &error_structure
257 );
258 ok(hfdi_unknown_fake != NULL,"FDICreate (CPU = unknown) (functions=fake) failed!\n");
259
260 hfdi_unknown_real = FDICreate(
|
261 rizwank 1.8 final_alloc,
262 final_free,
|
263 rizwank 1.7 real_open,
264 real_read,
265 dummy_write,
|
266 rizwank 1.8 real_close,
|
267 rizwank 1.7 dummy_seek,
268 cpuUNKNOWN,
269 &error_structure
270 );
271 ok(hfdi_unknown_real != NULL,"FDICreate (CPU = unknown) (functions=real) failed!\n");
272
273 printf("Ending TestCreate()\n");
274 }
275
276 static void TestInfo(void) {
|
277 rizwank 1.8 /* Noticed Behavior :
278 FDIIsCabinet does not open the file on its own, it requires a file open/close to be done externally.
279 WHY?
280 The only functions in HFDI that FDIIsCabinet directly accesses is FNREAD
281 Important cases to check :
282 If the filedescriptor == ERR, does it FAIL? (dummy_read)
283 If the filedescriptor == NOTCABINET, does it FAIL? (fake_read, real_read)
284 If the filedescriptor == CABINET, does it SUCCEED? (fake_read, real_read)
285 If the filedescriptor == CABINET, does it populate FDICABINETINFO? (fake_read, real_read)
286 */
287
|
288 rizwank 1.7 int realfd;
289 int sizer;
|
290 rizwank 1.8 FDICABINETINFO fdi_cabinfo_dummy, fdi_cabinfo_simple, fdi_cabinfo_complex;
|
291 rizwank 1.7
292 printf("Starting TestInfo()\n");
|
293 rizwank 1.8
294 /* TEST : ERR filehandle associated, dummy functions should return FALSE */
295 ok ( FDIIsCabinet( hfdi_unknown_dummy, -1, &fdi_cabinfo_dummy) == FALSE,
|
296 rizwank 1.7 "FDIIsCabinet (File = Error) failed!\n");
|
297 rizwank 1.8
298 /* TEST : Fake filehandle associated, memory manually copied, should return TRUE */
299 ok ( FDIIsCabinet( hfdi_unknown_fake, fakeFD, &fdi_cabinfo_simple) == TRUE,
300 "FDIIsCabinet (FakeFile = Cabinet) failed!\n");
301
302 ok ( fdi_cabinfo_simple.cbCabinet == 117, "FDIIsCabinet,cabinfo (FakeFile = Cabinet) data did not match! Failed!\n");
303 ok ( fdi_cabinfo_simple.cFolders == 1, "FDIIsCabinet,cabinfo (FakeFile = Cabinet) data did not match! Failed!\n");
304 ok ( fdi_cabinfo_simple.cFiles == 1, "FDIIsCabinet,cabinfo (FakeFile = Cabinet) data did not match! Failed!\n");
305 ok ( fdi_cabinfo_simple.setID == 12345, "FDIIsCabinet,cabinfo (FakeFile = Cabinet) data did not match! Failed!\n");
306 ok ( fdi_cabinfo_simple.iCabinet == 0, "FDIIsCabinet,cabinfo (FakeFile = Cabinet) data did not match! Failed!\n");
|
307 rizwank 2.0 ok ( fdi_cabinfo_simple.fReserve == 0, "FDIIsCabinet,cabinfo (FakeFile = Cabinet) data did not match! Failed!\n");
308 ok ( fdi_cabinfo_simple.hasprev == 0, "FDIIsCabinet,cabinfo (FakeFile = Cabinet) data did not match! Failed!\n");
309 ok ( fdi_cabinfo_simple.hasnext == 0, "FDIIsCabinet,cabinfo (FakeFile = Cabinet) data did not match! Failed!\n");
310
|
311 rizwank 1.8
|
312 rizwank 2.0 /* simply this with macros?
313 yes, make one macro with inputs (cabname, testname, [expected values] ) --- using lambda notation
314 add checks for cabinfo data!
315 Is it ok to reuse the same hfdi_unknown_real ? */
316
317 /* TEST : Opened filehandle associated, corrupted cab loaded, should return FALSE */
318 /* We can see that the Windows implementation only reads the first 36 bytes - what if we corrupted a CAB after 36 bytes?*/
319
320 realfd = real_open( "broken.cab" , _O_BINARY | _O_RDONLY | _O_SEQUENTIAL, 0);
321
322 ok ( FDIIsCabinet( hfdi_unknown_real, realfd, &fdi_cabinfo_complex) == FALSE,
323 "FDIIsCabinet (File = Bad-Cabinet) broken.cab failed!\n");
324 real_close(realfd);
325
326 realfd = real_open( "cabinet_fdi.c" , _O_BINARY | _O_RDONLY | _O_SEQUENTIAL, 0);
327
328 ok ( FDIIsCabinet( hfdi_unknown_real, realfd, &fdi_cabinfo_complex) == FALSE,
329 "FDIIsCabinet (File = Non-Cabinet) cabinet_fdi.c failed!\n");
330 real_close(realfd);
331
332
333 rizwank 2.0 /* TEST : Opened filehandle associated, valid cab loaded, should return TRUE */
334 realfd = real_open( "complex_lzw.cab" , _O_BINARY | _O_RDONLY | _O_SEQUENTIAL, 0);
335
336 ok ( FDIIsCabinet( hfdi_unknown_real, realfd, &fdi_cabinfo_complex) == TRUE,
337 "FDIIsCabinet (File = Cabinet) complex_lzw.cab failed!\n");
338 real_close(realfd);
339
340 printf("Cabinet Data : cbC %d cF %d cFi %d si %d iC %d fr %b hp %d hn %d\n",
341 fdi_cabinfo_complex.cbCabinet,
342 fdi_cabinfo_complex.cFolders ,
343 fdi_cabinfo_complex.cFiles ,
344 fdi_cabinfo_complex.setID,
345 fdi_cabinfo_complex.iCabinet,
346 fdi_cabinfo_complex.fReserve ,
347 fdi_cabinfo_complex.hasprev ,
348 fdi_cabinfo_complex.hasnext );
349
350 realfd = real_open( "complex_lzw2.cab" , _O_BINARY | _O_RDONLY | _O_SEQUENTIAL, 0);
351
352 ok ( FDIIsCabinet( hfdi_unknown_real, realfd, &fdi_cabinfo_complex) == TRUE,
353 "FDIIsCabinet (File = Cabinet) complex_lzw2.cab failed!\n");
354 rizwank 2.0 real_close(realfd);
355
356 printf("Cabinet Data : cbC %d cF %d cFi %d si %d iC %d fr %b hp %d hn %d\n",
357 fdi_cabinfo_complex.cbCabinet,
358 fdi_cabinfo_complex.cFolders ,
359 fdi_cabinfo_complex.cFiles ,
360 fdi_cabinfo_complex.setID,
361 fdi_cabinfo_complex.iCabinet,
362 fdi_cabinfo_complex.fReserve ,
363 fdi_cabinfo_complex.hasprev ,
364 fdi_cabinfo_complex.hasnext );
365
366 realfd = real_open( "complex_zip.cab" , _O_BINARY | _O_RDONLY | _O_SEQUENTIAL, 0);
367
|
368 rizwank 1.8 ok ( FDIIsCabinet( hfdi_unknown_real, realfd, &fdi_cabinfo_complex) == TRUE,
|
369 rizwank 2.0 "FDIIsCabinet (File = Cabinet) complex_zip.cab failed!\n");
|
370 rizwank 1.8 real_close(realfd);
|
371 rizwank 1.7
|
372 rizwank 2.0 printf("Cabinet Data : cbC %d cF %d cFi %d si %d iC %d fr %b hp %d hn %d\n",
|
373 rizwank 1.8 fdi_cabinfo_complex.cbCabinet,
374 fdi_cabinfo_complex.cFolders ,
375 fdi_cabinfo_complex.cFiles ,
376 fdi_cabinfo_complex.setID,
377 fdi_cabinfo_complex.iCabinet,
378 fdi_cabinfo_complex.fReserve ,
379 fdi_cabinfo_complex.hasprev ,
380 fdi_cabinfo_complex.hasnext );
|
381 rizwank 2.0
382 realfd = real_open( "complex_zip2.cab" , _O_BINARY | _O_RDONLY | _O_SEQUENTIAL, 0);
383
384 ok ( FDIIsCabinet( hfdi_unknown_real, realfd, &fdi_cabinfo_complex) == TRUE,
385 "FDIIsCabinet (File = Cabinet) complex_zip2.cab failed!\n");
386 real_close(realfd);
387
388 printf("Cabinet Data : cbC %d cF %d cFi %d si %d iC %d fr %b hp %d hn %d\n",
389 fdi_cabinfo_complex.cbCabinet,
390 fdi_cabinfo_complex.cFolders ,
391 fdi_cabinfo_complex.cFiles ,
392 fdi_cabinfo_complex.setID,
393 fdi_cabinfo_complex.iCabinet,
394 fdi_cabinfo_complex.fReserve ,
395 fdi_cabinfo_complex.hasprev ,
396 fdi_cabinfo_complex.hasnext );
397
398 realfd = real_open( "complex_none.cab" , _O_BINARY | _O_RDONLY | _O_SEQUENTIAL, 0);
399
400 ok ( FDIIsCabinet( hfdi_unknown_real, realfd, &fdi_cabinfo_complex) == TRUE,
401 "FDIIsCabinet (File = Cabinet) complex_zip.cab failed!\n");
402 rizwank 2.0 real_close(realfd);
403
404 printf("Cabinet Data : cbC %d cF %d cFi %d si %d iC %d fr %b hp %d hn %d\n",
405 fdi_cabinfo_complex.cbCabinet,
406 fdi_cabinfo_complex.cFolders ,
407 fdi_cabinfo_complex.cFiles ,
408 fdi_cabinfo_complex.setID,
409 fdi_cabinfo_complex.iCabinet,
410 fdi_cabinfo_complex.fReserve ,
411 fdi_cabinfo_complex.hasprev ,
412 fdi_cabinfo_complex.hasnext );
413
|
414 rizwank 1.7
415 }
416
417 static void TestDestroy(void) {
418 printf("Starting TestDestroy()\n");
|
419 rizwank 2.0 /* Should return TRUE if given a valid hfdi, else FALSE (only due to context errors?) */
420
|
421 rizwank 1.7 ok(FDIDestroy(hfdi_unknown_dummy), "FDIDestroy (CPU = unknown) (functions=fake) failed!\n");
422 ok(FDIDestroy(hfdi_unknown_fake), "FDIDestroy (CPU = unknown) (functions=fake) failed!\n");
|
423 rizwank 2.0 ok(FDIDestroy(hfdi_unknown_real), "FDIDestroy (CPU = unknown) (functions=real) failed!\n");
|
424 rizwank 1.7 printf("Ending TestDestroy()\n");
|
425 rizwank 1.5
|
426 rizwank 1.4 }
|
427 rizwank 1.1
428 START_TEST(paths)
429 {
|
430 rizwank 1.4 TestCreate();
|
431 rizwank 1.7 TestInfo();
|
432 rizwank 1.2 /*
433 TestCopy();
|
434 rizwank 1.3 */
|
435 rizwank 1.2 TestDestroy();
|
436 rizwank 1.1 }
|