version 1.5, 2005/02/04 09:37:43
|
version 2.13, 2005/03/11 07:38:58
|
|
|
/* | /* |
* Unit test suite for cabinet.dll - FDI functions | * Unit test suite for cabinet.dll - FDI functions |
* | * |
* Copyright 2004 Rizwan Kassim, Dan Kegel |
* Copyright 2004 Rizwan Kassim, Dan Kegel, Alexander Liber |
* | * |
* This library is free software; you can redistribute it and/or | * This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public | * modify it under the terms of the GNU Lesser General Public |
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
*/ | */ |
| |
|
#include <stdio.h> |
#include <stdlib.h> | #include <stdlib.h> |
|
#include <string.h> |
|
#include <sys/stat.h> |
|
#include <stdarg.h> |
|
#include <malloc.h> |
|
|
|
#include <stdarg.h> |
|
#include <stdio.h> |
|
|
|
#include "windef.h" |
|
#include "winbase.h" |
|
#include "winerror.h" |
|
#include "fdi.h" |
|
|
|
#ifndef WIN_ENV |
|
#include <msvcrt/fcntl.h> |
|
#else |
|
#include <fcntl.h> |
|
#endif |
|
|
|
#include "tvfs.h" |
|
#include "data.h" |
| |
#ifndef STANDALONE | #ifndef STANDALONE |
#include <wine/test.h> | #include <wine/test.h> |
|
#define _S_IREAD 0x0100 |
|
#define _S_IWRITE 0x0080 |
#define ok2 ok | #define ok2 ok |
#else | #else |
/* To build outside Wine tree, compile with cl -DSTANDALONE -D_X86_ cabinet_fdi.c FDI.lib |
/* To build outside Wine tree, compile with cl -DSTANDALONE -D_X86_ -DWIN_ENV tvfs.c cabinet_fdi.c FDI.lib |
These are only called if standalone are used, defining ok and START_TEST, which would normally be declared in winetree */ | These are only called if standalone are used, defining ok and START_TEST, which would normally be declared in winetree */ |
#include <assert.h> | #include <assert.h> |
#include <stdio.h> |
|
#define START_TEST(name) main(int argc, char **argv) | #define START_TEST(name) main(int argc, char **argv) |
#define ok(condition, msg) \ | #define ok(condition, msg) \ |
do { if(!(condition)) { \ | do { if(!(condition)) { \ |
|
|
exit(1); \ | exit(1); \ |
} } while(0) | } } while(0) |
#define todo_wine | #define todo_wine |
#endif |
|
| |
|
static void trace(const char *s, ...) |
|
{ |
|
va_list ellipsis; |
|
va_start (ellipsis, s); |
|
vprintf(s, ellipsis); |
|
va_end(ellipsis); |
|
} |
| |
#include <winerror.h> |
#endif |
#include <fdi.h> |
|
| |
/* To do in FDI: -from wine/include/fdi.h |
/* Do malloc and free output debug messages? |
FDICreate |
#define DEBUG_ALLOC |
Memory Allocation -FNALLOC(cb) |
#define VERBOSE |
Memory Free -FNFREE(pv) |
|
File Open -FNOPEN(pszFile,oflag,pmode) |
|
File Read -FNREAD(hf, pv, cb) |
|
File Write -FNWRITE(hf, pv, cb) |
|
File Close -FNCLOSE(hf) |
|
File Seek -FNSEEK(hf,dist,seektype) |
|
Error Structure |
|
FDIlsCabinet |
|
FDICabinetInfo Structure |
|
FDICopy |
|
Notification function |
|
Decryption function |
|
FDIDestroy |
|
*/ | */ |
| |
/* Currently mostly dummy function pointers */ |
#ifndef DEBUG_ALLOC |
|
FNALLOC(final_alloc) { |
FNALLOC(debug_alloc) { |
|
printf(" FNALLOC just called with %d\n",cb); |
|
return malloc(cb); | return malloc(cb); |
} | } |
|
FNFREE(final_free) { |
FNFREE(debug_free) { |
|
printf(" FNFREE just called with %d\n",pv); |
|
free(pv); | free(pv); |
return; | return; |
} | } |
|
#else |
/* |
FNALLOC(final_alloc) { |
It is not necessary for these functions to actually call _open etc.; these functions could instead call fopen, fread, fwrite, fclose, and fseek, or CreateFile, ReadFile, WriteFile, CloseHandle, and SetFilePointer, etc. However, the parameters and return codes will have to be translated appropriately (e.g. the file open mode passed in to pfnopen). |
trace(" FNALLOC just called with %d\n",cb); |
|
return malloc(cb); |
|
} |
|
FNFREE(final_free) { |
|
trace(" FNFREE just called with %d\n",pv); |
|
free(pv); |
|
return; |
|
} |
|
#endif |
|
/*Possible non trivial addition: |
|
Notify receives some information about the cab file(see FDI documentation). |
|
Since this info is different depending on the value of fdint, and Notify should |
|
be generic, it is not simple or nice to check this information. |
*/ | */ |
|
FNFDINOTIFY(notification_function) |
FNOPEN(dummy_open) { |
{ |
printf(" FNOPEN just called with %d, %d, %d\n",pszFile, oflag, pmode); |
#ifdef VERBOSE |
|
trace(" FNFDINOTIFY real just called with %d, %d \n",fdint,pfdin); |
|
#endif |
|
switch (fdint) |
|
{ |
|
case fdintCABINET_INFO: |
|
{ |
|
#ifdef VERBOSE |
|
trace( |
|
"fdintCABINET_INFO:\n" |
|
"-next cab name: %s\n" |
|
"-next disk: %s\n" |
|
"-path name: %s\n" |
|
"-set ID: %d\n" |
|
"-number in set: %d\n", |
|
pfdin->psz1, |
|
pfdin->psz2, |
|
pfdin->psz3, |
|
pfdin->setID, |
|
pfdin->iCabinet |
|
); |
|
#endif |
return 0; | return 0; |
} | } |
|
case fdintPARTIAL_FILE: |
|
{ |
|
#ifdef VERBOSE |
|
trace("dintPARTIAL_FILE\n"); |
|
#endif |
| |
FNREAD(dummy_read) { |
|
printf(" FNREAD just called with %d, %d, %d\n",hf, pv, cb); |
|
return 0; | return 0; |
} | } |
|
case fdintCOPY_FILE: |
|
{ |
|
int fih = 0; |
|
char target[256]; |
|
#ifdef VERBOSE |
|
trace( |
|
"fdintCOPY_FILE:\n" |
|
"-name: %s\n" |
|
"-uncompressed size: %d\n" |
|
"-date: %d\n" |
|
"-time: %d\n" |
|
"-attributes: %d\n" |
|
"-file's folder index: %d\n", |
|
pfdin->psz1, |
|
pfdin->cb, |
|
pfdin->date, |
|
pfdin->time, |
|
pfdin->attribs, |
|
pfdin->iFolder |
|
); |
|
#endif |
|
sprintf(target, "./%s",pfdin->psz1); |
|
fih = tvfs_open (target, |
|
_O_BINARY | _O_CREAT | _O_WRONLY | _O_SEQUENTIAL, |
|
_S_IREAD | _S_IWRITE |
|
); |
|
return fih; |
|
} |
|
case fdintCLOSE_FILE_INFO: |
|
{ |
|
#ifdef VERBOSE |
|
trace( |
|
"fdintCLOSE_FILE:\n" |
|
"-name: %s\n" |
|
"-handle: %d\n" |
|
"-date: %d\n" |
|
"-time: %d\n" |
|
"-attributes: %d\n" |
|
"-file's folder index: %d\n" |
|
"-run: %d\n", |
|
pfdin->psz1, |
|
pfdin->hf, |
|
pfdin->date, |
|
pfdin->time, |
|
pfdin->attribs, |
|
pfdin->iFolder, |
|
pfdin->cb |
|
); |
|
#endif |
| |
FNWRITE(dummy_write) { |
tvfs_close(pfdin->hf); |
printf(" FNWRITE just called with %d, %d, %d\n",hf, pv, cb); |
return TRUE; |
|
} |
|
case fdintNEXT_CABINET: |
|
{ |
|
#ifdef VERBOSE |
|
trace("fdintNEXT_CABINET\n"); |
|
#endif |
return 0; | return 0; |
} | } |
|
case fdintENUMERATE: |
|
{ |
FNCLOSE(dummy_close) { |
#ifdef VERBOSE |
printf(" FNCLOSE just called with %d\n",hf); |
trace("fdintENUMERATE\n"); |
|
#endif |
return 0; | return 0; |
} | } |
|
} |
FNSEEK(dummy_seek) { |
|
printf(" FNSEEK just called with %d, %d, %d\n",hf, dist, seektype); |
|
return 0; | return 0; |
} | } |
| |
HFDI hfdi_386, hfdi_286, hfdi_unknown; |
static void printCabInfo(FDICABINETINFO cabinfo){ |
/* yes its global and ugly */ |
#ifdef VERBOSE |
|
trace(" Cabinet Data : cbC %d cF %d cFi %d si %d iC %d fr %d hp %d hn %d\n", |
static void TestDestroy(void) { |
cabinfo.cbCabinet, |
printf("Starting TestDestroy()\n"); |
cabinfo.cFolders , |
/* Only two things to check in FDIDestroy |
cabinfo.cFiles , |
1=> Does it return T if its passed an hfdi |
cabinfo.setID, |
2=> Does it return F if its passed a non hfdi |
cabinfo.iCabinet, |
EDIT : Causes GPL if FDIDestroy is called on an invalid pointer. |
cabinfo.fReserve , |
ok( 0 == FDIDestroy(0), "Return true incorrectly in TestDestroy()!\n"); |
cabinfo.hasprev , |
*/ |
cabinfo.hasnext ); |
ok(FDIDestroy(hfdi_386), "Failed on destroying 386 hfdi!\n"); |
#endif |
ok(FDIDestroy(hfdi_286), "Failed on destroying 286 hfdi!\n"); |
} |
ok(FDIDestroy(hfdi_unknown), "Failed on destroying unknown hfdi!\n"); |
|
printf("Ending TestDestroy()\n"); |
|
| |
|
static void CheckCabInfo(char * cabname, |
|
FDICABINETINFO cabinfo, |
|
long TcbCabinet, |
|
USHORT TcFolders, |
|
USHORT TcFiles, |
|
USHORT TsetID, |
|
USHORT TiCabinet, |
|
BOOL TfReserve, |
|
BOOL Thasprev, |
|
BOOL Thasnext){ |
|
ok2 ( cabinfo.cbCabinet == TcbCabinet, "FDIIsCabinet,cabinfo %s data did not match! Failed!\n", cabname); |
|
ok2 ( cabinfo.cFolders == TcFolders, "FDIIsCabinet,cabinfo %s data did not match! Failed!\n", cabname); |
|
ok2 ( cabinfo.cFiles == TcFiles, "FDIIsCabinet,cabinfo %s data did not match! Failed!\n", cabname); |
|
ok2 ( cabinfo.setID == TsetID, "FDIIsCabinet,cabinfo %s data did not match! Failed!\n", cabname); |
|
ok2 ( cabinfo.iCabinet == TiCabinet, "FDIIsCabinet,cabinfo %s data did not match! Failed!\n", cabname); |
|
ok2 ( cabinfo.fReserve == TfReserve, "FDIIsCabinet,cabinfo %s data did not match! Failed!\n", cabname); |
|
ok2 ( cabinfo.hasprev == Thasprev, "FDIIsCabinet,cabinfo %s data did not match! Failed!\n", cabname); |
|
ok2 ( cabinfo.hasnext == Thasnext, "FDIIsCabinet,cabinfo %s data did not match! Failed!\n", cabname); |
} | } |
| |
static void TestCreate(void) { |
static HFDI hfdi_unknown; |
|
/* yes its global and ugly */ |
| |
ERF error_structure; |
/* Is CPU386 or Unknown more commonly used? */ |
| |
printf("Starting TestCreate()\n"); |
static void TestCreate(void) { |
| |
hfdi_386 = FDICreate( |
ERF error_structure; |
debug_alloc, |
|
debug_free, |
|
dummy_open, |
|
dummy_read, |
|
dummy_write, |
|
dummy_close, |
|
dummy_seek, |
|
cpu80386, |
|
&error_structure |
|
); |
|
ok(hfdi_386 != NULL,"FDICreate (CPU = cpu80386) failed!\n"); |
|
| |
hfdi_286 = FDICreate( |
trace("Starting TestCreate()\n"); |
debug_alloc, |
|
debug_free, |
|
dummy_open, |
|
dummy_read, |
|
dummy_write, |
|
dummy_close, |
|
dummy_seek, |
|
cpu80286, |
|
&error_structure |
|
); |
|
ok(hfdi_286 != NULL,"FDICreate (CPU = cpu80286) failed!\n"); |
|
| |
hfdi_unknown = FDICreate( | hfdi_unknown = FDICreate( |
debug_alloc, |
final_alloc, |
debug_free, |
final_free, |
dummy_open, |
tvfs_open, tvfs_read, tvfs_write, tvfs_close, tvfs_lseek, |
dummy_read, |
|
dummy_write, |
|
dummy_close, |
|
dummy_seek, |
|
cpuUNKNOWN, | cpuUNKNOWN, |
&error_structure | &error_structure |
); | ); |
ok(hfdi_unknown != NULL,"FDICreate (CPU = unknown) failed!\n"); |
|
| |
|
ok(hfdi_unknown != NULL,"FDICreate (CPU = unknown) (functions=tvfs) failed!\n"); |
|
|
|
trace("Ending TestCreate()\n"); |
|
} |
|
|
|
static void TestInfo(void) { |
|
|
|
int fd; |
| |
|
FDICABINETINFO fdi_cabinfo_simple, fdi_cabinfo_complex; |
| |
|
trace("Starting TestInfo()\n"); |
| |
printf("Ending TestCreate()\n"); |
tvfs_create( name_simple_cab, file_simple_cab, size_simple_cab); |
|
fd = tvfs_open( name_simple_cab, _O_BINARY, 0 ); |
|
|
|
ok( FDIIsCabinet( hfdi_unknown, fd, &fdi_cabinfo_simple) == TRUE, |
|
"FDIIsCabinet (Virtual File = Simple.cab) failed!\n"); |
|
|
|
printCabInfo(fdi_cabinfo_simple); |
|
CheckCabInfo("simple.cab",fdi_cabinfo_simple,121,1,1,0,0,0,0,0); |
|
|
|
tvfs_close(fd); |
|
|
|
tvfs_create( name_complex_cab, file_complex_cab, size_complex_cab); |
|
fd = tvfs_open( name_complex_cab, _O_BINARY, 0 ); |
|
|
|
ok( FDIIsCabinet( hfdi_unknown, fd, &fdi_cabinfo_complex) == TRUE, |
|
"FDIIsCabinet (Virtual File = Complex.cab) failed!\n"); |
|
|
|
printCabInfo(fdi_cabinfo_complex); |
|
CheckCabInfo("complex.cab",fdi_cabinfo_complex,12918,1,2,0,0,0,0,0); |
|
|
|
tvfs_close(fd); |
|
tvfs_free(); |
|
|
|
trace("Ending TestInfo()\n"); |
} | } |
| |
START_TEST(paths) |
static void TestCopy(void){ |
{ |
|
|
char name_file_path[256]; |
|
int result; |
|
|
|
trace("Starting TestCopy()\n"); |
|
trace("---simple.cab\n"); |
|
|
|
tvfs_create( name_simple_cab, file_simple_cab, size_simple_cab); |
|
FDICopy(hfdi_unknown, |
|
"simple.cab", |
|
"", |
|
0, |
|
notification_function, |
|
NULL, |
|
NULL); |
|
|
|
/* Filename when extracted is ./<filename> */ |
|
sprintf(name_file_path, "./%s", name_simple_txt); |
|
result = tvfs_compare(name_file_path, file_simple_txt, size_simple_txt); |
|
if (result) |
|
trace ("File %s compare failed!\n",name_file_path); |
|
tvfs_free(); |
|
|
|
trace("---complex.cab\n"); |
|
tvfs_create( name_complex_cab, file_complex_cab, size_complex_cab); |
|
FDICopy(hfdi_unknown, |
|
"complex.cab", |
|
"", |
|
0, |
|
notification_function, |
|
NULL, |
|
NULL); |
| |
|
|
|
tvfs_free(); |
|
|
|
trace("Ending TestCopy()\n"); |
|
} |
|
|
|
static void TestDestroy(void) { |
|
trace("Starting TestDestroy()\n"); |
|
ok(FDIDestroy(hfdi_unknown), "FDIDestroy (CPU = unknown) (functions=tvfs) failed!\n"); |
|
trace("Ending TestDestroy()\n"); |
|
} |
|
|
|
START_TEST(cabinet_fdi) |
|
{ |
TestCreate(); | TestCreate(); |
/* |
|
TestInfo(); | TestInfo(); |
TestCopy(); | TestCopy(); |
*/ |
|
TestDestroy(); | TestDestroy(); |
|
tvfs_free(); |
} | } |