Signed-off-by: Michael Stefaniuc mstefani@winehq.org --- v2: Clear desc before calling GetDescriptor()
dlls/dmime/tests/dmime.c | 222 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 222 insertions(+)
diff --git a/dlls/dmime/tests/dmime.c b/dlls/dmime/tests/dmime.c index 62a977eeb7..b7b8095725 100644 --- a/dlls/dmime/tests/dmime.c +++ b/dlls/dmime/tests/dmime.c @@ -21,7 +21,9 @@ #include <stdarg.h> #include <windef.h> #include <wine/test.h> +#include <ole2.h> #include <dmusici.h> +#include <dmusicf.h> #include <audioclient.h> #include <guiddef.h>
@@ -617,6 +619,225 @@ static void test_track(void) } }
+struct chunk { + FOURCC id; + DWORD size; + FOURCC type; +}; + +#define CHUNK_HDR_SIZE (sizeof(FOURCC) + sizeof(DWORD)) + +/* Generate a RIFF file format stream from an array of FOURCC ids. + RIFF and LIST need to be followed by the form type respectively list type, + followed by the chunks of the list and terminated with 0. */ +static IStream *gen_riff_stream(const FOURCC *ids) +{ + static const LARGE_INTEGER zero; + int level = -1; + DWORD *sizes[4]; /* Stack for the sizes of RIFF and LIST chunks */ + char riff[1024]; + char *p = riff; + struct chunk *ck; + IStream *stream; + + do { + ck = (struct chunk *)p; + ck->id = *ids++; + switch (ck->id) { + case 0: + *sizes[level] = p - (char *)sizes[level] - sizeof(DWORD); + level--; + break; + case FOURCC_LIST: + case FOURCC_RIFF: + level++; + sizes[level] = &ck->size; + ck->type = *ids++; + p += sizeof(*ck); + break; + case DMUS_FOURCC_GUID_CHUNK: + ck->size = sizeof(GUID_NULL); + p += CHUNK_HDR_SIZE; + memcpy(p, &GUID_NULL, sizeof(GUID_NULL)); + p += ck->size; + break; + case DMUS_FOURCC_VERSION_CHUNK: + { + DMUS_VERSION ver = {5, 8}; + + ck->size = sizeof(ver); + p += CHUNK_HDR_SIZE; + memcpy(p, &ver, sizeof(ver)); + p += ck->size; + break; + } + default: + { + /* Just convert the FOURCC id to a WCHAR string */ + WCHAR *s; + + ck->size = 5 * sizeof(WCHAR); + p += CHUNK_HDR_SIZE; + s = (WCHAR *)p; + s[0] = (char)(ck->id); + s[1] = (char)(ck->id >> 8); + s[2] = (char)(ck->id >> 16); + s[3] = (char)(ck->id >> 24); + s[4] = 0; + p += ck->size; + } + } + } while (level >= 0); + + ck = (struct chunk *)riff; + CreateStreamOnHGlobal(NULL, TRUE, &stream); + IStream_Write(stream, riff, ck->size + CHUNK_HDR_SIZE, NULL); + IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL); + + return stream; +} + +static void test_parsedescriptor(void) +{ + IDirectMusicObject *dmo; + IStream *stream; + DMUS_OBJECTDESC desc; + HRESULT hr; + DWORD valid; + unsigned int i; + const WCHAR s_unam[] = {'U','N','A','M','\0'}; + const WCHAR s_inam[] = {'I','\0'}; + /* fourcc ~0 will be replaced later on */ + FOURCC alldesc[] = + { + FOURCC_RIFF, ~0, DMUS_FOURCC_CATEGORY_CHUNK, FOURCC_LIST, DMUS_FOURCC_UNFO_LIST, + DMUS_FOURCC_UNAM_CHUNK, DMUS_FOURCC_UCOP_CHUNK, DMUS_FOURCC_UCMT_CHUNK, + DMUS_FOURCC_USBJ_CHUNK, 0, DMUS_FOURCC_VERSION_CHUNK, DMUS_FOURCC_GUID_CHUNK, 0 + }; + FOURCC dupes[] = + { + FOURCC_RIFF, ~0, DMUS_FOURCC_CATEGORY_CHUNK, DMUS_FOURCC_CATEGORY_CHUNK, + DMUS_FOURCC_VERSION_CHUNK, DMUS_FOURCC_VERSION_CHUNK, DMUS_FOURCC_GUID_CHUNK, + DMUS_FOURCC_GUID_CHUNK, FOURCC_LIST, DMUS_FOURCC_UNFO_LIST, DMUS_FOURCC_UNAM_CHUNK, 0, + FOURCC_LIST, DMUS_FOURCC_UNFO_LIST, mmioFOURCC('I','N','A','M'), 0, 0 + }; + FOURCC empty[] = {FOURCC_RIFF, ~0, 0}; + FOURCC inam[] = {FOURCC_RIFF, ~0, FOURCC_LIST, ~0, mmioFOURCC('I','N','A','M'), 0, 0}; +#define X(form) form, #form + const struct { + FOURCC form; + const char *name; + } forms[] = { + { X(DMUS_FOURCC_SEGMENT_FORM) }, + { X(mmioFOURCC('W','A','V','E')) }, + }; +#undef X + + hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER, + &IID_IDirectMusicObject, (void **)&dmo); + if (hr != S_OK) { + win_skip("Could not create DirectMusicSegment object: %08x\n", hr); + return; + } + for (i = 0; i < ARRAY_SIZE(forms); i++) { + trace("Testing %s\n", forms[i].name); + + /* Nothing loaded */ + memset(&desc, 0, sizeof(desc)); + hr = IDirectMusicObject_GetDescriptor(dmo, &desc); + ok(hr == S_OK, "GetDescriptor failed: %08x, expected S_OK\n", hr); + ok(desc.dwValidData == DMUS_OBJ_CLASS, "Got valid data %#x, expected DMUS_OBJ_CLASS\n", + desc.dwValidData); + ok(IsEqualGUID(&desc.guidClass, &CLSID_DirectMusicSegment), + "Got class guid %s, expected CLSID_DirectMusicSegment\n", + wine_dbgstr_guid(&desc.guidClass)); + + /* Empty RIFF stream */ + empty[1] = forms[i].form; + stream = gen_riff_stream(empty); + memset(&desc, 0, sizeof(desc)); + hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc); + ok(hr == S_OK, "ParseDescriptor failed: %08x, expected S_OK\n", hr); + ok(desc.dwValidData == DMUS_OBJ_CLASS, "Got valid data %#x, expected DMUS_OBJ_CLASS\n", + desc.dwValidData); + ok(IsEqualGUID(&desc.guidClass, &CLSID_DirectMusicSegment), + "Got class guid %s, expected CLSID_DirectMusicSegment\n", + wine_dbgstr_guid(&desc.guidClass)); + IStream_Release(stream); + + /* Wrong form */ + empty[1] = DMUS_FOURCC_CONTAINER_FORM; + stream = gen_riff_stream(empty); + memset(&desc, 0, sizeof(desc)); + hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc); + ok(hr == E_FAIL, "ParseDescriptor failed: %08x, expected S_OK\n", hr); + todo_wine ok(!desc.dwValidData, "Got valid data %#x, expected 0\n", desc.dwValidData); + + /* All desc chunks */ + alldesc[1] = forms[i].form; + stream = gen_riff_stream(alldesc); + memset(&desc, 0, sizeof(desc)); + hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc); + ok(hr == S_OK, "ParseDescriptor failed: %08x, expected S_OK\n", hr); + valid = DMUS_OBJ_OBJECT | DMUS_OBJ_CLASS | DMUS_OBJ_VERSION; + if (forms[i].form == DMUS_FOURCC_SEGMENT_FORM) + valid |= DMUS_OBJ_NAME | DMUS_OBJ_CATEGORY; + todo_wine_if(forms[i].form == mmioFOURCC('W','A','V','E')) + ok(desc.dwValidData == valid, "Got valid data %#x, expected %#x\n", desc.dwValidData, + valid); + ok(IsEqualGUID(&desc.guidClass, &CLSID_DirectMusicSegment), + "Got class guid %s, expected %s\n", wine_dbgstr_guid(&desc.guidClass), + wine_dbgstr_guid(&CLSID_DirectMusicSegment)); + ok(IsEqualGUID(&desc.guidObject, &GUID_NULL), "Got object guid %s, expected GUID_NULL\n", + wine_dbgstr_guid(&desc.guidClass)); + if (forms[i].form == DMUS_FOURCC_SEGMENT_FORM) + ok(!memcmp(desc.wszName, s_unam, sizeof(s_unam)), "Got name '%s', expected 'UNAM'\n", + wine_dbgstr_w(desc.wszName)); + IStream_Release(stream); + + /* Duplicated chunks */ + dupes[1] = forms[i].form; + stream = gen_riff_stream(dupes); + memset(&desc, 0, sizeof(desc)); + hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc); + ok(hr == S_OK, "ParseDescriptor failed: %08x, expected S_OK\n", hr); + todo_wine_if(forms[i].form == mmioFOURCC('W','A','V','E')) + ok(desc.dwValidData == valid, "Got valid data %#x, expected %#x\n", desc.dwValidData, + valid); + IStream_Release(stream); + + /* UNFO list with INAM */ + inam[1] = forms[i].form; + inam[3] = DMUS_FOURCC_UNFO_LIST; + stream = gen_riff_stream(inam); + memset(&desc, 0, sizeof(desc)); + hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc); + ok(hr == S_OK, "ParseDescriptor failed: %08x, expected S_OK\n", hr); + todo_wine_if(forms[i].form == DMUS_FOURCC_SEGMENT_FORM) + ok(desc.dwValidData == DMUS_OBJ_CLASS, "Got valid data %#x, expected DMUS_OBJ_CLASS\n", + desc.dwValidData); + IStream_Release(stream); + + /* INFO list with INAM */ + inam[3] = DMUS_FOURCC_INFO_LIST; + stream = gen_riff_stream(inam); + memset(&desc, 0, sizeof(desc)); + hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc); + ok(hr == S_OK, "ParseDescriptor failed: %08x, expected S_OK\n", hr); + valid = DMUS_OBJ_CLASS; + if (forms[i].form == mmioFOURCC('W','A','V','E')) + valid |= DMUS_OBJ_NAME; + todo_wine_if(forms[i].form == mmioFOURCC('W','A','V','E')) + ok(desc.dwValidData == valid, "Got valid data %#x, expected %#x\n", desc.dwValidData, + valid); + if (forms[i].form == mmioFOURCC('W','A','V','E')) + todo_wine ok(!memcmp(desc.wszName, s_inam, sizeof(s_inam)), + "Got name '%s', expected 'I'\n", wine_dbgstr_w(desc.wszName)); + IStream_Release(stream); + } + IDirectMusicObject_Release(dmo); +} + START_TEST(dmime) { CoInitialize(NULL); @@ -637,6 +858,7 @@ START_TEST(dmime) test_graph(); test_segment(); test_track(); + test_parsedescriptor();
CoUninitialize(); }