mirror of
git://source.winehq.org/git/wine.git
synced 2024-11-01 15:39:00 +00:00
msi/tests: automation: Add tests for SummaryInfo::Property, get.
This commit is contained in:
parent
68d4e65c5e
commit
f2c10a530c
1 changed files with 183 additions and 21 deletions
|
@ -37,8 +37,9 @@ static const WCHAR szMSITEST[] = { 'M','S','I','T','E','S','T',0 };
|
|||
static const WCHAR szProductCode[] = { '{','F','1','C','3','A','F','5','0','-','8','B','5','6','-','4','A','6','9','-','A','0','0','C','-','0','0','7','7','3','F','E','4','2','F','3','0','}',0 };
|
||||
static const WCHAR szUpgradeCode[] = { '{','C','E','0','6','7','E','8','D','-','2','E','1','A','-','4','3','6','7','-','B','7','3','4','-','4','E','B','2','B','D','A','D','6','5','6','5','}',0 };
|
||||
static const WCHAR szProductInfoException[] = { 'P','r','o','d','u','c','t','I','n','f','o',',','P','r','o','d','u','c','t',',','A','t','t','r','i','b','u','t','e',0 };
|
||||
CHAR CURR_DIR[MAX_PATH];
|
||||
EXCEPINFO excepinfo;
|
||||
static FILETIME systemtime;
|
||||
static CHAR CURR_DIR[MAX_PATH];
|
||||
static EXCEPINFO excepinfo;
|
||||
|
||||
/*
|
||||
* OLE automation data
|
||||
|
@ -187,6 +188,30 @@ static const msi_table tables[] =
|
|||
ADD_TABLE(service_control)
|
||||
};
|
||||
|
||||
typedef struct _msi_summary_info
|
||||
{
|
||||
UINT property;
|
||||
UINT datatype;
|
||||
INT iValue;
|
||||
FILETIME *pftValue;
|
||||
const CHAR *szValue;
|
||||
} msi_summary_info;
|
||||
|
||||
#define ADD_INFO_I2(property, iValue) {property, VT_I2, iValue, NULL, NULL}
|
||||
#define ADD_INFO_I4(property, iValue) {property, VT_I4, iValue, NULL, NULL}
|
||||
#define ADD_INFO_LPSTR(property, szValue) {property, VT_LPSTR, 0, NULL, szValue}
|
||||
#define ADD_INFO_FILETIME(property, pftValue) {property, VT_FILETIME, 0, pftValue, NULL}
|
||||
|
||||
static const msi_summary_info summary_info[] =
|
||||
{
|
||||
ADD_INFO_LPSTR(PID_TEMPLATE, ";1033"),
|
||||
ADD_INFO_LPSTR(PID_REVNUMBER, "{004757CA-5092-49c2-AD20-28E1CE0DF5F2}"),
|
||||
ADD_INFO_I4(PID_PAGECOUNT, 100),
|
||||
ADD_INFO_I4(PID_WORDCOUNT, 0),
|
||||
ADD_INFO_FILETIME(PID_CREATE_DTM, &systemtime),
|
||||
ADD_INFO_FILETIME(PID_LASTPRINTED, &systemtime)
|
||||
};
|
||||
|
||||
/*
|
||||
* Database Helpers
|
||||
*/
|
||||
|
@ -202,26 +227,24 @@ static void write_file(const CHAR *filename, const char *data, int data_size)
|
|||
CloseHandle(hf);
|
||||
}
|
||||
|
||||
static void write_msi_summary_info(MSIHANDLE db)
|
||||
static void write_msi_summary_info(MSIHANDLE db, const msi_summary_info *info, int num_info)
|
||||
{
|
||||
MSIHANDLE summary;
|
||||
UINT r;
|
||||
int j;
|
||||
|
||||
r = MsiGetSummaryInformationA(db, NULL, 4, &summary);
|
||||
r = MsiGetSummaryInformationA(db, NULL, num_info, &summary);
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
|
||||
|
||||
r = MsiSummaryInfoSetPropertyA(summary, PID_TEMPLATE, VT_LPSTR, 0, NULL, ";1033");
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
|
||||
/* import summary information into the stream */
|
||||
for (j = 0; j < num_info; j++)
|
||||
{
|
||||
const msi_summary_info *entry = &info[j];
|
||||
|
||||
r = MsiSummaryInfoSetPropertyA(summary, PID_REVNUMBER, VT_LPSTR, 0, NULL,
|
||||
"{004757CA-5092-49c2-AD20-28E1CE0DF5F2}");
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
|
||||
|
||||
r = MsiSummaryInfoSetPropertyA(summary, PID_PAGECOUNT, VT_I4, 100, NULL, NULL);
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
|
||||
|
||||
r = MsiSummaryInfoSetPropertyA(summary, PID_WORDCOUNT, VT_I4, 0, NULL, NULL);
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
|
||||
r = MsiSummaryInfoSetPropertyA(summary, entry->property, entry->datatype,
|
||||
entry->iValue, entry->pftValue, entry->szValue);
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
|
||||
}
|
||||
|
||||
/* write the summary changes back to the stream */
|
||||
r = MsiSummaryInfoPersist(summary);
|
||||
|
@ -230,7 +253,8 @@ static void write_msi_summary_info(MSIHANDLE db)
|
|||
MsiCloseHandle(summary);
|
||||
}
|
||||
|
||||
static void create_database(const CHAR *name, const msi_table *tables, int num_tables)
|
||||
static void create_database(const CHAR *name, const msi_table *tables, int num_tables,
|
||||
const msi_summary_info *info, int num_info)
|
||||
{
|
||||
MSIHANDLE db;
|
||||
UINT r;
|
||||
|
@ -252,7 +276,7 @@ static void create_database(const CHAR *name, const msi_table *tables, int num_t
|
|||
DeleteFileA(table->filename);
|
||||
}
|
||||
|
||||
write_msi_summary_info(db);
|
||||
write_msi_summary_info(db, info, num_info);
|
||||
|
||||
r = MsiDatabaseCommit(db);
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
|
||||
|
@ -367,7 +391,7 @@ static void check_service_is_installed(void)
|
|||
* Automation helpers and tests
|
||||
*/
|
||||
|
||||
/* ok-like statement which takes two unicode strings as arguments */
|
||||
/* ok-like statement which takes two unicode strings or one unicode and one ANSI string as arguments */
|
||||
static CHAR string1[MAX_PATH], string2[MAX_PATH];
|
||||
|
||||
#define ok_w2(format, szString1, szString2) \
|
||||
|
@ -379,6 +403,18 @@ static CHAR string1[MAX_PATH], string2[MAX_PATH];
|
|||
ok(0, format, string1, string2); \
|
||||
}
|
||||
|
||||
#define ok_aw(format, aString, wString) \
|
||||
\
|
||||
WideCharToMultiByte(CP_ACP, 0, wString, -1, string1, MAX_PATH, NULL, NULL); \
|
||||
if (lstrcmpA(string1, aString) != 0) \
|
||||
ok(0, format, string1, aString); \
|
||||
|
||||
#define ok_awplus(format, extra, aString, wString) \
|
||||
\
|
||||
WideCharToMultiByte(CP_ACP, 0, wString, -1, string1, MAX_PATH, NULL, NULL); \
|
||||
if (lstrcmpA(string1, aString) != 0) \
|
||||
ok(0, format, extra, string1, aString); \
|
||||
|
||||
/* exception checker */
|
||||
static WCHAR szSource[] = {'M','s','i',' ','A','P','I',' ','E','r','r','o','r',0};
|
||||
|
||||
|
@ -584,6 +620,8 @@ static void test_dispatch(void)
|
|||
}
|
||||
|
||||
/* invocation helper function */
|
||||
static int _invoke_todo_vtResult = 0;
|
||||
|
||||
static HRESULT invoke(IDispatch *pDispatch, LPCSTR szName, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, VARTYPE vtResult)
|
||||
{
|
||||
OLECHAR *name = NULL;
|
||||
|
@ -609,7 +647,10 @@ static HRESULT invoke(IDispatch *pDispatch, LPCSTR szName, WORD wFlags, DISPPARA
|
|||
|
||||
if (hr == S_OK)
|
||||
{
|
||||
ok(V_VT(pVarResult) == vtResult, "Variant result type is %d, expected %d\n", V_VT(pVarResult), vtResult);
|
||||
if (_invoke_todo_vtResult) todo_wine
|
||||
ok(V_VT(pVarResult) == vtResult, "Variant result type is %d, expected %d\n", V_VT(pVarResult), vtResult);
|
||||
else
|
||||
ok(V_VT(pVarResult) == vtResult, "Variant result type is %d, expected %d\n", V_VT(pVarResult), vtResult);
|
||||
if (vtResult != VT_EMPTY)
|
||||
{
|
||||
hr = VariantChangeTypeEx(pVarResult, pVarResult, LOCALE_NEUTRAL, 0, vtResult);
|
||||
|
@ -1032,6 +1073,22 @@ static HRESULT Database_OpenView(IDispatch *pDatabase, LPCWSTR szSql, IDispatch
|
|||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT Database_SummaryInformation(IDispatch *pDatabase, int iUpdateCount, IDispatch **pSummaryInfo)
|
||||
{
|
||||
VARIANT varresult;
|
||||
VARIANTARG vararg[1];
|
||||
DISPPARAMS dispparams = {vararg, NULL, sizeof(vararg)/sizeof(VARIANTARG), 0};
|
||||
HRESULT hr;
|
||||
|
||||
VariantInit(&vararg[0]);
|
||||
V_VT(&vararg[0]) = VT_I4;
|
||||
V_I4(&vararg[0]) = iUpdateCount;
|
||||
|
||||
hr = invoke(pDatabase, "SummaryInformation", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_DISPATCH);
|
||||
*pSummaryInfo = V_DISPATCH(&varresult);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT View_Execute(IDispatch *pView, IDispatch *pRecord)
|
||||
{
|
||||
VARIANT varresult;
|
||||
|
@ -1193,8 +1250,100 @@ static HRESULT StringList_Count(IDispatch *pStringList, int *pCount)
|
|||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT SummaryInfo_PropertyGet(IDispatch *pSummaryInfo, int pid, VARIANT *pVarResult, VARTYPE vtExpect)
|
||||
{
|
||||
VARIANTARG vararg[1];
|
||||
DISPPARAMS dispparams = {vararg, NULL, sizeof(vararg)/sizeof(VARIANTARG), 0};
|
||||
|
||||
VariantInit(&vararg[0]);
|
||||
V_VT(&vararg[0]) = VT_I4;
|
||||
V_I4(&vararg[0]) = pid;
|
||||
return invoke(pSummaryInfo, "Property", DISPATCH_PROPERTYGET, &dispparams, pVarResult, vtExpect);
|
||||
}
|
||||
|
||||
/* Test the various objects */
|
||||
|
||||
static void test_SummaryInfo(IDispatch *pSummaryInfo, const msi_summary_info *info, int num_info)
|
||||
{
|
||||
static const WCHAR szPropertyException[] = { 'P','r','o','p','e','r','t','y',',','P','i','d',0 };
|
||||
VARIANT varresult;
|
||||
HRESULT hr;
|
||||
int j;
|
||||
|
||||
/* SummaryInfo::Property, get for properties we have set */
|
||||
for (j = 0; j < num_info; j++)
|
||||
{
|
||||
const msi_summary_info *entry = &info[j];
|
||||
|
||||
int vt = entry->datatype;
|
||||
if (vt == VT_LPSTR) vt = VT_BSTR;
|
||||
else if (vt == VT_FILETIME) vt = VT_DATE;
|
||||
|
||||
hr = SummaryInfo_PropertyGet(pSummaryInfo, entry->property, &varresult, vt);
|
||||
ok(hr == S_OK, "SummaryInfo_Property (pid %d) failed, hresult 0x%08x\n", entry->property, hr);
|
||||
if (V_VT(&varresult) != vt)
|
||||
skip("Skipping property tests due to type mismatch\n");
|
||||
else if (vt == VT_I2)
|
||||
ok(V_I2(&varresult) == entry->iValue, "SummaryInfo_Property (pid %d) I2 result expected to be %d, but was %d\n",
|
||||
entry->property, entry->iValue, V_I2(&varresult));
|
||||
else if (vt == VT_I4)
|
||||
ok(V_I4(&varresult) == entry->iValue, "SummaryInfo_Property (pid %d) I4 result expected to be %d, but was %d\n",
|
||||
entry->property, entry->iValue, V_I4(&varresult));
|
||||
else if (vt == VT_DATE) todo_wine
|
||||
{
|
||||
SYSTEMTIME st;
|
||||
FILETIME ft;
|
||||
DATE d;
|
||||
|
||||
FileTimeToLocalFileTime(entry->pftValue, &ft);
|
||||
FileTimeToSystemTime(&ft, &st);
|
||||
SystemTimeToVariantTime(&st, &d);
|
||||
ok(d == V_DATE(&varresult), "SummaryInfo_Property (pid %d) DATE result expected to be %lf, but was %lf\n", entry->property, d, V_DATE(&varresult));
|
||||
}
|
||||
else if (vt == VT_BSTR)
|
||||
{
|
||||
ok_awplus("SummaryInfo_Property (pid %d) BSTR result expected to be %s, but was %s\n", entry->property, entry->szValue, V_BSTR(&varresult));
|
||||
}
|
||||
else
|
||||
skip("SummaryInfo_Property (pid %d) unhandled result type %d\n", entry->property, vt);
|
||||
}
|
||||
|
||||
/* SummaryInfo::Property, get; invalid arguments */
|
||||
|
||||
/* Invalid pids */
|
||||
hr = SummaryInfo_PropertyGet(pSummaryInfo, -1, &varresult, VT_EMPTY);
|
||||
todo_wine ok(hr == DISP_E_EXCEPTION, "SummaryInfo_PropertyGet failed, hresult 0x%08x\n", hr);
|
||||
ok_exception(hr, szPropertyException);
|
||||
|
||||
hr = SummaryInfo_PropertyGet(pSummaryInfo, 1000, &varresult, VT_EMPTY);
|
||||
todo_wine ok(hr == DISP_E_EXCEPTION, "SummaryInfo_PropertyGet failed, hresult 0x%08x\n", hr);
|
||||
ok_exception(hr, szPropertyException);
|
||||
|
||||
/* Unsupported pids */
|
||||
hr = SummaryInfo_PropertyGet(pSummaryInfo, PID_DICTIONARY, &varresult, VT_EMPTY);
|
||||
ok(hr == S_OK, "SummaryInfo_PropertyGet failed, hresult 0x%08x\n", hr);
|
||||
|
||||
hr = SummaryInfo_PropertyGet(pSummaryInfo, PID_THUMBNAIL, &varresult, VT_EMPTY);
|
||||
ok(hr == S_OK, "SummaryInfo_PropertyGet failed, hresult 0x%08x\n", hr);
|
||||
|
||||
/* Pids we have not set, one for each type */
|
||||
_invoke_todo_vtResult = 1;
|
||||
|
||||
hr = SummaryInfo_PropertyGet(pSummaryInfo, PID_CODEPAGE, &varresult, VT_EMPTY);
|
||||
ok(hr == S_OK, "SummaryInfo_PropertyGet failed, hresult 0x%08x\n", hr);
|
||||
|
||||
hr = SummaryInfo_PropertyGet(pSummaryInfo, PID_TITLE, &varresult, VT_EMPTY);
|
||||
todo_wine ok(hr == S_OK, "SummaryInfo_PropertyGet failed, hresult 0x%08x\n", hr);
|
||||
|
||||
hr = SummaryInfo_PropertyGet(pSummaryInfo, PID_EDITTIME, &varresult, VT_EMPTY);
|
||||
ok(hr == S_OK, "SummaryInfo_PropertyGet failed, hresult 0x%08x\n", hr);
|
||||
|
||||
hr = SummaryInfo_PropertyGet(pSummaryInfo, PID_CHARCOUNT, &varresult, VT_EMPTY);
|
||||
ok(hr == S_OK, "SummaryInfo_PropertyGet failed, hresult 0x%08x\n", hr);
|
||||
|
||||
_invoke_todo_vtResult = 0;
|
||||
}
|
||||
|
||||
static void test_Database(IDispatch *pDatabase)
|
||||
{
|
||||
static WCHAR szSql[] = { 'S','E','L','E','C','T',' ','`','F','e','a','t','u','r','e','`',' ','F','R','O','M',' ','`','F','e','a','t','u','r','e','`',' ','W','H','E','R','E',' ','`','F','e','a','t','u','r','e','_','P','a','r','e','n','t','`','=','\'','O','n','e','\'',0 };
|
||||
|
@ -1202,7 +1351,7 @@ static void test_Database(IDispatch *pDatabase)
|
|||
static WCHAR szTwo[] = { 'T','w','o',0 };
|
||||
static WCHAR szStringDataField[] = { 'S','t','r','i','n','g','D','a','t','a',',','F','i','e','l','d',0 };
|
||||
static WCHAR szModifyModeRecord[] = { 'M','o','d','i','f','y',',','M','o','d','e',',','R','e','c','o','r','d',0 };
|
||||
IDispatch *pView = NULL;
|
||||
IDispatch *pView = NULL, *pSummaryInfo = NULL;
|
||||
HRESULT hr;
|
||||
|
||||
hr = Database_OpenView(pDatabase, szSql, &pView);
|
||||
|
@ -1298,6 +1447,16 @@ static void test_Database(IDispatch *pDatabase)
|
|||
|
||||
IDispatch_Release(pView);
|
||||
}
|
||||
|
||||
/* Database::SummaryInformation */
|
||||
hr = Database_SummaryInformation(pDatabase, 0, &pSummaryInfo);
|
||||
ok(hr == S_OK, "Database_SummaryInformation failed, hresult 0x%08x\n", hr);
|
||||
ok(pSummaryInfo != NULL, "Database_SummaryInformation should not have returned NULL record\n");
|
||||
if (pSummaryInfo)
|
||||
{
|
||||
test_SummaryInfo(pSummaryInfo, summary_info, sizeof(summary_info)/sizeof(msi_summary_info));
|
||||
IDispatch_Release(pSummaryInfo);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_Session(IDispatch *pSession)
|
||||
|
@ -2032,7 +2191,8 @@ static void test_Installer(void)
|
|||
}
|
||||
|
||||
/* Prepare package */
|
||||
create_database(msifile, tables, sizeof(tables) / sizeof(msi_table));
|
||||
create_database(msifile, tables, sizeof(tables) / sizeof(msi_table),
|
||||
summary_info, sizeof(summary_info) / sizeof(msi_summary_info));
|
||||
|
||||
len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, CURR_DIR, -1, szPath, MAX_PATH);
|
||||
ok(len, "MultiByteToWideChar returned error %d\n", GetLastError());
|
||||
|
@ -2107,6 +2267,8 @@ START_TEST(automation)
|
|||
CLSID clsid;
|
||||
IUnknown *pUnk;
|
||||
|
||||
GetSystemTimeAsFileTime(&systemtime);
|
||||
|
||||
GetCurrentDirectoryA(MAX_PATH, prev_path);
|
||||
GetTempPath(MAX_PATH, temp_path);
|
||||
SetCurrentDirectoryA(temp_path);
|
||||
|
|
Loading…
Reference in a new issue