Hi,
I still have some fixes for avifile here, but because they are quite nasty, I thought it'd be useful to have proper tests to show the fixes are really correct.
Unfortunately there is still a problem with the avifile tests as Detlef indicated in this mail: http://www.winehq.org/pipermail/wine-devel/2009-November/079693.html
Based on Detlef's patch however, I was able to create an initial patch which should provide the base for the tests I want to add. I have attached it here.
The idea of the tests is that I write out a complete AVI file with the stdio functions and then read it back in using the VFW API and test the values in the different headers through the API. Later tests will change the values of the default headers and test how this affects the headers when they are being read back in. (I discovered Windows' avifil32 overrides some headers with values from other headers, there is some more info in my previous mails.)
The inlining structure of the current header file is now actually based on the RIFF tree in the AVI file. Is this useful or should I just use plain indentation? Should the avi file data really be put in an extra header or should it be merged with api.c? What do you think of the general idea of the tests?
Thanks a lot in advance for your feedback! Julius
From 00dc5fa4d767b2edbb0e9d42931c0fd9585c1b90 Mon Sep 17 00:00:00 2001 From: Julius Schwartzenberg julius.schwartzenberg@gmail.com Date: Fri, 25 Dec 2009 20:29:43 +0100 Subject: initial version of avifile testing framework
--- dlls/avifil32/tests/api.c | 72 ++++++++++++++++++ dlls/avifil32/tests/api_test.h | 160 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 232 insertions(+), 0 deletions(-) create mode 100644 dlls/avifil32/tests/api_test.h
diff --git a/dlls/avifil32/tests/api.c b/dlls/avifil32/tests/api.c index 55b194f..c41ebfb 100644 --- a/dlls/avifil32/tests/api.c +++ b/dlls/avifil32/tests/api.c @@ -20,6 +20,7 @@ */
#include <stdarg.h> +#include <stdio.h>
#include "windef.h" #include "winbase.h" @@ -28,6 +29,8 @@ #include "vfw.h" #include "wine/test.h"
+#include "api_test.h" + /* ########################### */
static const CHAR winetest0[] = "winetest0"; @@ -87,11 +90,80 @@ static void test_AVISaveOptions(void)
/* ########################### */
+void init_test_struct(COMMON_AVI_HEADERS *cah) +{ + MainAVIHeader *mah = malloc(sizeof(MainAVIHeader)); + AVIStreamHeader *ash0 = malloc(sizeof(AVIStreamHeader)); + AVIStreamHeader *ash1 = malloc(sizeof(AVIStreamHeader)); + PCMWAVEFORMAT *pcmwf = malloc(sizeof(PCMWAVEFORMAT)); + memcpy(mah, &defmah, sizeof(defmah)); + memcpy(ash0, &defash0, sizeof(defash0)); + memcpy(ash1, &defash1, sizeof(defash1)); + memcpy(pcmwf, &defpcmwf, sizeof(defpcmwf)); + cah->mah = mah; + cah->ash0 = ash0; + cah->ash1 = ash1; + cah->pcmwf = pcmwf; +} + +void create_avi_file(COMMON_AVI_HEADERS *cah) +{ + FILE * pFile; + pFile = fopen("small.avi", "wb"); + + fwrite(file_header, 1, sizeof(file_header), pFile); /* de file wordt hier niet goed aangemaakt */ + fwrite(cah->mah, 1, sizeof(MainAVIHeader), pFile); + fwrite(streamlist, 1, sizeof(streamlist), pFile); + fwrite(cah->ash0, 1, 0x38, pFile); + fwrite(videostreamformat, 1, sizeof(videostreamformat), pFile); + fwrite(padding1, 1, sizeof(padding1), pFile); + fwrite(videopropheader, 1, sizeof(videopropheader), pFile); + fwrite(cah->ash1, 1, 0x38, pFile); + fwrite(audiostreamformat_pre, 1, sizeof(audiostreamformat_pre), pFile); + fwrite(cah->pcmwf, 1, sizeof(PCMWAVEFORMAT), pFile); + fwrite(data, 1, sizeof(data), pFile); + + fclose (pFile); +} + +void test_default_data() +{ + COMMON_AVI_HEADERS *cah; + PAVIFILE pFile; + int res; + LONG lSize; + WAVEFORMATEX wfx; + PAVISTREAM pStream; + + cah = calloc(sizeof(int),4); + init_test_struct(cah); + create_avi_file(cah); + + res = AVIFileOpen(&pFile, "small.avi", OF_SHARE_DENY_WRITE, 0L); + ok(res == 0, "Unable to open file: error=%u\n", res); + + res = AVIFileGetStream(pFile, &pStream, 0, 1); + ok(res == 0, "Unable to open audio stream: error=%u\n", res); + + ok(AVIStreamReadFormat(pStream, AVIStreamStart(pStream), NULL, &lSize) == 0, "Unable to read format size\n"); + ok(AVIStreamReadFormat(pStream, AVIStreamStart(pStream), &wfx, &lSize) == 0, "Unable to read format\n"); + + ok(wfx.wFormatTag == 1, "got %u (expected 1)\n",wfx.wFormatTag); + ok(wfx.nChannels == 2, "got %u (expected 2)\n",wfx.nChannels); + ok(wfx.wFormatTag == 1, "got %u (expected 1)\n",wfx.wFormatTag); + ok(wfx.nSamplesPerSec == 11025, "got %u (expected 11025)\n",wfx.nSamplesPerSec); + ok(wfx.nAvgBytesPerSec == 22050, "got %u (expected 22050)\n",wfx.nAvgBytesPerSec); + ok(wfx.nBlockAlign == 2, "got %u (expected 2)\n",wfx.nBlockAlign); +} + +/* ########################### */ + START_TEST(api) {
AVIFileInit(); test_AVISaveOptions(); + test_default_data(); AVIFileExit();
} diff --git a/dlls/avifil32/tests/api_test.h b/dlls/avifil32/tests/api_test.h new file mode 100644 index 0000000..395cfa3 --- /dev/null +++ b/dlls/avifil32/tests/api_test.h @@ -0,0 +1,160 @@ +/* + * Unit test suite header for AVI Functions + * + * Copyright 2009 Julius Schwartzenberg + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + */ + + +typedef struct common_avi_headers { + MainAVIHeader *mah; + AVIStreamHeader *ash0; + AVIStreamHeader *ash1; + PCMWAVEFORMAT *pcmwf; +} COMMON_AVI_HEADERS; + +static const MainAVIHeader defmah = +{ + 0x00008256, /* dwMicroSecPerFrame */ + 0x000080e8, /* dwMaxBytesPerSec */ + 0x00000000, /* dwPaddingGranularity */ + 0x00000910, /* dwFlags */ + 1, /* dwTotalFrames */ + 0, /* dwInitialFrames */ + 2, /* dwStreams */ + 0x00100000, /* dwSuggestedBufferSize*/ + 8, /* dwWidth */ + 6, /* dwHeight */ + { 0, 0, 0, 0 } /* dwReserved[4] */ +}; + +static const AVIStreamHeader defash0 = +{ + streamtypeVIDEO, /* fccType */ + 0x30323449, /* fccHandler */ + 0x00000000, /* dwFlags */ + 0, /* wPriority */ + 0, /* wLanguage */ + 0, /* dwInitialFrames */ + 0x000003e9, /* dwScale */ + 0x00007530, /* dwRate */ + 0, /* dwStart */ + 1, /* dwLength */ + 0x00100000, /* dwSuggestedBufferSize*/ + 0xffffffff, /* dwQuality */ + 0, /* dwSampleSize */ + { 0, 0, 0, 0 } /* short left right top bottom */ +}; + +static const AVIStreamHeader defash1 = +{ + /* AVIStreamHeader */ + streamtypeAUDIO, /* fccType */ + 1, /* fccHandler */ + 0, /* dwFlags */ + 0, /* wPriority */ + 0, /* wLanguage */ + 0, /* dwInitialFrames */ + 1, /* dwScale */ + 0x00002b11, /* dwRate */ + 0, /* dwStart */ + 0x00000665, /* dwLength */ + 0x00003000, /* dwSuggestedBufferSize*/ + 0xffffffff, /* dwQuality */ + 2, /* dwSampleSize */ + { 0, 0, 0, 0 } /* short left right top bottom */ +}; + +static const PCMWAVEFORMAT defpcmwf = +{ + { + 1, /* wFormatTag */ + 2, /* nChannels */ + 11025, /* nSamplesPerSec */ + 22050, /* nAvgBytesPerSec */ + 2, /* nBlockAlign */ + }, + 8, /* wBitsPerSample */ +}; + +/* Extra data needed to get the VFW API to load the file */ +DWORD file_header[] = +{ + FOURCC_RIFF, 0x34c6 /* length */, formtypeAVI, + FOURCC_LIST, 0x1ac /* length */, + listtypeAVIHEADER, ckidAVIMAINHDR, sizeof(MainAVIHeader), +}; + +/* MainAVIHeader mah */ + +DWORD streamlist[] = +{ + FOURCC_LIST, 0xd4 /* length */, + listtypeSTREAMHEADER, ckidSTREAMHEADER, 0x38 /* length */, +}; + +/* AVIStreamHeader ash0 */ + +DWORD videostreamformat[] = +{ + ckidSTREAMFORMAT, 0x28 /* length */, + 0x00000028, 0x00000008, 0x00000006, 0x00180001, + 0x30323449, 0x00000090, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, +}; +DWORD padding1[] = +{ + ckidAVIPADDING, 0xc /* length */, + 0x00000004, 0x00000000, 0x63643030 +}; +DWORD videopropheader[] = +{ + 0x70727076, 0x44 /* length */, + 0x00000000, 0x00000000, + 0x0000001e, 0x00000008, 0x00000006, 0x00100009, + 0x00000008, 0x00000006, 0x00000001, 0x00000006, + 0x00000008, 0x00000006, 0x00000008, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, + FOURCC_LIST, 0x70 /* length */, + listtypeSTREAMHEADER, ckidSTREAMHEADER, 0x38 /* length */, +}; + +/* AVIStreamHeader ash1 */ + +DWORD audiostreamformat_pre[] = +{ + ckidSTREAMFORMAT, sizeof(PCMWAVEFORMAT) /* length */, +}; + +/* PCMWAVEFORMAT pcmwf */ + +DWORD data[] = +{ + ckidAVIPADDING, 0xc /* length */, + 0x00000004, 0x00000000, 0x62773130, + ckidAVIPADDING, 0xc /* length */, + 0x6c6d646f, 0x686c6d64, 0x000000f8, + FOURCC_LIST, 0x18 /* length */, + 0x4f464e49, + 0x54465349, 0xc /* length */, + 0x6676614c, 0x332e3235, 0x00302e37, + ckidAVIPADDING, 0x4 /* length */, + 0, + + FOURCC_LIST, 0xd1b /* length */, listtypeAVIMOVIE, + 0, 0 +};
Julius Schwartzenberg schrieb:
What do you think of the general idea of the tests?
Hi Julius, As i cant proof correctness here, i just can say that the general idea is great. Until Bug 14085 is fixed you can todo_wine it out. Further i think you can leave the data in the c-file(we also have raw manifest data in c-files), but it should not be that hard to move it to a header.
Hi André
André Hentschel wrote:
Julius Schwartzenberg schrieb:
What do you think of the general idea of the tests?
As i cant proof correctness here, i just can say that the general
idea is great.
Until Bug 14085 is fixed you can todo_wine it out. Further i think
you can leave the data in the c-file(we also have raw manifest data in c-files), but it should not be that hard to move it to a header.
Thanks for your feedback! I don't think I can use todo_wine to work around this bug though or am I mistaken here? I kinda hope someone with a good J-rank is motivated by my patches to solve the problem ;)
As by Dmitry's suggestion, I indeed moved all data to api.c now.
Regards, Julius
Hi Julius,
"Julius Schwartzenberg" julius.schwartzenberg@gmail.com wrote:
+#include "api_test.h"
If the definitions in api_test.h are used only in 1 source file there is no need to create an .h file at all, just place all the data in that source file.
+void init_test_struct(COMMON_AVI_HEADERS *cah)
This should be static, same as all other functions and data structures below.
+{
- MainAVIHeader *mah = malloc(sizeof(MainAVIHeader));
- AVIStreamHeader *ash0 = malloc(sizeof(AVIStreamHeader));
- AVIStreamHeader *ash1 = malloc(sizeof(AVIStreamHeader));
- PCMWAVEFORMAT *pcmwf = malloc(sizeof(PCMWAVEFORMAT));
- memcpy(mah, &defmah, sizeof(defmah));
- memcpy(ash0, &defash0, sizeof(defash0));
- memcpy(ash1, &defash1, sizeof(defash1));
- memcpy(pcmwf, &defpcmwf, sizeof(defpcmwf));
- cah->mah = mah;
- cah->ash0 = ash0;
- cah->ash1 = ash1;
- cah->pcmwf = pcmwf;
+}
malloc() should not be used in the Wine code. Also, since you allocate fixed buffer sizes it would be simpler to have structures not pointers to the structures inside main structure.
+void create_avi_file(COMMON_AVI_HEADERS *cah)
'cah' should be const.
+{
- FILE * pFile;
- pFile = fopen("small.avi", "wb");
- fwrite(file_header, 1, sizeof(file_header), pFile); /* de file wordt hier niet goed aangemaakt */
- fwrite(cah->mah, 1, sizeof(MainAVIHeader), pFile);
- fwrite(streamlist, 1, sizeof(streamlist), pFile);
- fwrite(cah->ash0, 1, 0x38, pFile);
- fwrite(videostreamformat, 1, sizeof(videostreamformat), pFile);
- fwrite(padding1, 1, sizeof(padding1), pFile);
- fwrite(videopropheader, 1, sizeof(videopropheader), pFile);
- fwrite(cah->ash1, 1, 0x38, pFile);
- fwrite(audiostreamformat_pre, 1, sizeof(audiostreamformat_pre), pFile);
- fwrite(cah->pcmwf, 1, sizeof(PCMWAVEFORMAT), pFile);
- fwrite(data, 1, sizeof(data), pFile);
- fclose (pFile);
+}
Please use CreateFile()/WriteFile()/etc. instead of fopen/fwrite/etc.
+void test_default_data()
Please don't omit 'void' in case of no parameters.
+{
- COMMON_AVI_HEADERS *cah;
- PAVIFILE pFile;
- int res;
- LONG lSize;
- WAVEFORMATEX wfx;
- PAVISTREAM pStream;
- cah = calloc(sizeof(int),4);
Same comment as for malloc above. Also this can't work.
- init_test_struct(cah);
- create_avi_file(cah);
- res = AVIFileOpen(&pFile, "small.avi", OF_SHARE_DENY_WRITE, 0L);
- ok(res == 0, "Unable to open file: error=%u\n", res);
- res = AVIFileGetStream(pFile, &pStream, 0, 1);
- ok(res == 0, "Unable to open audio stream: error=%u\n", res);
- ok(AVIStreamReadFormat(pStream, AVIStreamStart(pStream), NULL, &lSize) == 0, "Unable to read format size\n");
- ok(AVIStreamReadFormat(pStream, AVIStreamStart(pStream), &wfx, &lSize) == 0, "Unable to read format\n");
Please use 'res' as an intermediate result storage as you do above.
+static const PCMWAVEFORMAT defpcmwf = +{
- {
- 1, /* wFormatTag */
- 2, /* nChannels */
- 11025, /* nSamplesPerSec */
- 22050, /* nAvgBytesPerSec */
- 2, /* nBlockAlign */
- },
- 8, /* wBitsPerSample */
+};
Indentation of above structure and all others below this one look strange. 4 spaces would be quite enough.
Do you really need all that separate structures? Wouldn't it be simpler to have a single buffer like in dlls/winmm/tests/mmio.c?
Hi Dmitry,
Thanks a lot for your feedback! I should've solved most issues you pointed me at. I have attached a new version of the patch.
Dmitry Timoshkov wrote:
Indentation of above structure and all others below this one look strange. 4 spaces would be quite enough.
This was supposed to represent the RIFF tree with the headers being tested taken out. The bottom part of the data is just needed to allow both Windows' VFW and Wine's VFW to load the file.
Roderick also just found the indentation strange, so I got rid of it now.
Do you really need all that separate structures? Wouldn't it be simpler to have a single buffer like in dlls/winmm/tests/mmio.c?
The reasons I chose to separate the structures: To be able to separate the headers out that I specifically want to test. I added an actual test to this version which shows how I imagine it to be used. The values can be easily 'corrupted' now using the structures as defined by the actual VFW headers. To keep some structure. I only took a proper look at the audio stream, but if someone has more knowledge on the video stream, they may now just take the videopropheader array, move it up in the source, structure it properly and write tests against it.
With the attached patch, all tests pass on MS Windows XP.
Regards, Julius
From 50ecf7728c68b60ebcff0c5e46e8332d124f1266 Mon Sep 17 00:00:00 2001
From: Julius Schwartzenberg julius.schwartzenberg@gmail.com Date: Fri, 25 Dec 2009 20:29:43 +0100 Subject: initial version of avifile testing framework plus the first simple tests
--- dlls/avifil32/tests/api.c | 320 +++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 320 insertions(+), 0 deletions(-)
diff --git a/dlls/avifil32/tests/api.c b/dlls/avifil32/tests/api.c index 55b194f..cfef4dc 100644 --- a/dlls/avifil32/tests/api.c +++ b/dlls/avifil32/tests/api.c @@ -35,6 +35,138 @@ static const CHAR winetest1[] = "winetest1";
/* ########################### */
+typedef struct common_avi_headers { + MainAVIHeader mah; + AVIStreamHeader ash0; + AVIStreamHeader ash1; + PCMWAVEFORMAT pcmwf; +} COMMON_AVI_HEADERS; + +static const MainAVIHeader defmah = +{ + 0x00008256, /* dwMicroSecPerFrame */ + 0x000080e8, /* dwMaxBytesPerSec */ + 0x00000000, /* dwPaddingGranularity */ + 0x00000910, /* dwFlags */ + 1, /* dwTotalFrames */ + 0, /* dwInitialFrames */ + 2, /* dwStreams */ + 0x00100000, /* dwSuggestedBufferSize*/ + 8, /* dwWidth */ + 6, /* dwHeight */ + { 0, 0, 0, 0 } /* dwReserved[4] */ +}; + +static const AVIStreamHeader defash0 = +{ + streamtypeVIDEO, /* fccType */ + 0x30323449, /* fccHandler */ + 0x00000000, /* dwFlags */ + 0, /* wPriority */ + 0, /* wLanguage */ + 0, /* dwInitialFrames */ + 0x000003e9, /* dwScale */ + 0x00007530, /* dwRate */ + 0, /* dwStart */ + 1, /* dwLength */ + 0x00100000, /* dwSuggestedBufferSize*/ + 0xffffffff, /* dwQuality */ + 0, /* dwSampleSize */ + { 0, 0, 0, 0 } /* short left right top bottom */ +}; + +static const AVIStreamHeader defash1 = +{ + /* AVIStreamHeader */ + streamtypeAUDIO, /* fccType */ + 1, /* fccHandler */ + 0, /* dwFlags */ + 0, /* wPriority */ + 0, /* wLanguage */ + 0, /* dwInitialFrames */ + 1, /* dwScale */ + 0x00002b11, /* dwRate */ + 0, /* dwStart */ + 0x00000665, /* dwLength */ + 0x00003000, /* dwSuggestedBufferSize*/ + 0xffffffff, /* dwQuality */ + 2, /* dwSampleSize */ + { 0, 0, 0, 0 } /* short left right top bottom */ +}; + +static const PCMWAVEFORMAT defpcmwf = +{ + { + 1, /* wFormatTag */ + 2, /* nChannels */ + 11025, /* nSamplesPerSec */ + 22050, /* nAvgBytesPerSec */ + 2, /* nBlockAlign */ + }, + 8, /* wBitsPerSample */ +}; + +/* Extra data needed to get the VFW API to load the file */ +static DWORD file_header[] = +{ + FOURCC_RIFF, 0x34c6 /* length */, formtypeAVI, + FOURCC_LIST, 0x1ac /* length */, + listtypeAVIHEADER, ckidAVIMAINHDR, sizeof(MainAVIHeader), +}; +/* MainAVIHeader mah */ +static DWORD streamlist[] = +{ + FOURCC_LIST, 0xd4 /* length */, + listtypeSTREAMHEADER, ckidSTREAMHEADER, 0x38 /* length */, +}; +/* AVIStreamHeader ash0 */ +static DWORD videostreamformat[] = +{ + ckidSTREAMFORMAT, 0x28 /* length */, + 0x00000028, 0x00000008, 0x00000006, 0x00180001, + 0x30323449, 0x00000090, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, +}; +static DWORD padding1[] = +{ + ckidAVIPADDING, 0xc /* length */, + 0x00000004, 0x00000000, 0x63643030 +}; +static DWORD videopropheader[] = +{ + 0x70727076, 0x44 /* length */, + 0x00000000, 0x00000000, + 0x0000001e, 0x00000008, 0x00000006, 0x00100009, + 0x00000008, 0x00000006, 0x00000001, 0x00000006, + 0x00000008, 0x00000006, 0x00000008, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, + FOURCC_LIST, 0x70 /* length */, + listtypeSTREAMHEADER, ckidSTREAMHEADER, 0x38 /* length */, +}; +/* AVIStreamHeader ash1 */ +static DWORD audiostreamformat_pre[] = +{ + ckidSTREAMFORMAT, sizeof(PCMWAVEFORMAT) /* length */, +}; +/* PCMWAVEFORMAT pcmwf */ +static DWORD data[] = +{ + ckidAVIPADDING, 0xc /* length */, + 0x00000004, 0x00000000, 0x62773130, + ckidAVIPADDING, 0xc /* length */, + 0x6c6d646f, 0x686c6d64, 0x000000f8, + FOURCC_LIST, 0x18 /* length */, + 0x4f464e49, + 0x54465349, 0xc /* length */, + 0x6676614c, 0x332e3235, 0x00302e37, + ckidAVIPADDING, 0x4 /* length */, + 0, + FOURCC_LIST, 0xd1b /* length */, listtypeAVIMOVIE, + 0, 0 +}; + +/* ########################### */ + static void test_AVISaveOptions(void) { AVICOMPRESSOPTIONS options[2]; @@ -87,11 +219,199 @@ static void test_AVISaveOptions(void)
/* ########################### */
+static void init_test_struct(COMMON_AVI_HEADERS *cah) +{ + memcpy(&cah->mah, &defmah, sizeof(defmah)); + memcpy(&cah->ash0, &defash0, sizeof(defash0)); + memcpy(&cah->ash1, &defash1, sizeof(defash1)); + memcpy(&cah->pcmwf, &defpcmwf, sizeof(defpcmwf)); +} + +static void create_avi_file(const COMMON_AVI_HEADERS *cah) +{ + HANDLE hFile; + DWORD written; + + hFile = CreateFile("small.avi", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + + ok(hFile != INVALID_HANDLE_VALUE, "Couldn't create file\n"); + + WriteFile(hFile, file_header, sizeof(file_header), &written, NULL); + WriteFile(hFile, &cah->mah, sizeof(MainAVIHeader), &written, NULL); + WriteFile(hFile, streamlist, sizeof(streamlist), &written, NULL); + WriteFile(hFile, &cah->ash0, 0x38, &written, NULL); + WriteFile(hFile, videostreamformat, sizeof(videostreamformat), &written, NULL); + WriteFile(hFile, padding1, sizeof(padding1), &written, NULL); + WriteFile(hFile, videopropheader, sizeof(videopropheader), &written, NULL); + WriteFile(hFile, &cah->ash1, 0x38, &written, NULL); + WriteFile(hFile, audiostreamformat_pre, sizeof(audiostreamformat_pre), &written, NULL); + WriteFile(hFile, &cah->pcmwf, sizeof(PCMWAVEFORMAT), &written, NULL); + WriteFile(hFile, data, sizeof(data), &written, NULL); + + CloseHandle(hFile); +} + +static void test_default_data(void) +{ + COMMON_AVI_HEADERS cah; + PAVIFILE pFile; + int res; + LONG lSize; + PAVISTREAM pStream0; + PAVISTREAM pStream1; + AVISTREAMINFO asi0; + AVISTREAMINFO asi1; + WAVEFORMATEX wfx; + + init_test_struct(&cah); + create_avi_file(&cah); + + res = AVIFileOpen(&pFile, "small.avi", OF_SHARE_DENY_WRITE, 0L); + ok(res == 0, "Unable to open file: error=%u\n", res); + + res = AVIFileGetStream(pFile, &pStream0, 0, 0); + ok(res == 0, "Unable to open video stream: error=%u\n", res); + + res = AVIFileGetStream(pFile, &pStream1, 0, 1); + ok(res == 0, "Unable to open audio stream: error=%u\n", res); + + res = AVIStreamInfo(pStream0, &asi0, sizeof(AVISTREAMINFO)); + ok(res == 0, "Unable to read stream info: error=%u\n", res); + + res = AVIStreamInfo(pStream1, &asi1, sizeof(AVISTREAMINFO)); + ok(res == 0, "Unable to read stream info: error=%u\n", res); + + res = AVIStreamReadFormat(pStream0, AVIStreamStart(pStream1), NULL, &lSize); + ok(res == 0, "Unable to read format size: error=%u\n", res); + + res = AVIStreamReadFormat(pStream1, AVIStreamStart(pStream1), &wfx, &lSize); + ok(res == 0, "Unable to read format: error=%u\n", res); + + ok(asi0.fccType == streamtypeVIDEO, "got 0x%x (expected streamtypeVIDEO)\n", asi0.fccType); + ok(asi0.fccHandler == 0x30323449, "got 0x%x (expected 0x30323449)\n", asi0.fccHandler); + ok(asi0.dwFlags == 0, "got %u (expected 0)\n", asi0.dwFlags); + ok(asi0.wPriority == 0, "got %u (expected 0)\n", asi0.wPriority); + ok(asi0.wLanguage == 0, "got %u (expected 0)\n", asi0.wLanguage); + ok(asi0.dwScale == 1001, "got %u (expected 1001)\n", asi0.dwScale); + ok(asi0.dwRate == 30000, "got %u (expected 30000)\n", asi0.dwRate); + ok(asi0.dwStart == 0, "got %u (expected 0)\n", asi0.dwStart); + ok(asi0.dwLength == 1, "got %u (expected 1)\n", asi0.dwLength); + ok(asi0.dwInitialFrames == 0, "got %u (expected 0)\n", asi0.dwInitialFrames); + ok(asi0.dwSuggestedBufferSize == 0, "got %u (expected 0)\n", asi0.dwSuggestedBufferSize); + ok(asi0.dwQuality == 0xffffffff, "got 0x%x (expected 0xffffffff)\n", asi0.dwQuality); + ok(asi0.dwSampleSize == 0, "got %u (expected 0)\n", asi0.dwSampleSize); + ok(asi0.rcFrame.left == 0, "got %u (expected 0)\n", asi0.rcFrame.left); + ok(asi0.rcFrame.top == 0, "got %u (expected 0)\n", asi0.rcFrame.top); + ok(asi0.rcFrame.right == 8, "got %u (expected 8)\n", asi0.rcFrame.right); /* these are based on the values in the mah and not */ + ok(asi0.rcFrame.bottom == 6, "got %u (expected 6)\n", asi0.rcFrame.bottom);/* on the ones in the ash which are 0 here */ + ok(asi0.dwEditCount == 0, "got %u (expected 0)\n", asi0.dwEditCount); + ok(asi0.dwFormatChangeCount == 0, "got %u (expected 0)\n)", asi0.dwFormatChangeCount); + + ok(asi1.fccType == streamtypeAUDIO, "got 0x%x (expected streamtypeVIDEO)\n", asi1.fccType); + ok(asi1.fccHandler == 0x1, "got 0x%x (expected 0x1)\n", asi1.fccHandler); + ok(asi1.dwFlags == 0, "got %u (expected 0)\n", asi1.dwFlags); + ok(asi1.wPriority == 0, "got %u (expected 0)\n", asi1.wPriority); + ok(asi1.wLanguage == 0, "got %u (expected 0)\n", asi1.wLanguage); + ok(asi1.dwScale == 1, "got %u (expected 1)\n", asi1.dwScale); + ok(asi1.dwRate == 11025, "got %u (expected 11025)\n", asi1.dwRate); + ok(asi1.dwStart == 0, "got %u (expected 0)\n", asi1.dwStart); + ok(asi1.dwLength == 1637, "got %u (expected 1637)\n", asi1.dwLength); + ok(asi1.dwInitialFrames == 0, "got %u (expected 0)\n", asi1.dwInitialFrames); + ok(asi1.dwSuggestedBufferSize == 0, "got %u (expected 0)\n", asi1.dwSuggestedBufferSize); + ok(asi1.dwQuality == 0xffffffff, "got 0x%x (expected 0xffffffff)\n", asi1.dwQuality); + ok(asi1.dwSampleSize == 2, "got %u (expected 2)\n", asi1.dwSampleSize); + ok(asi1.rcFrame.left == 0, "got %u (expected 0)\n", asi1.rcFrame.left); + ok(asi1.rcFrame.top == 0, "got %u (expected 0)\n", asi1.rcFrame.top); + ok(asi1.rcFrame.right == 0, "got %u (expected 0)\n", asi1.rcFrame.right); + ok(asi1.rcFrame.bottom == 0, "got %u (expected 0)\n", asi1.rcFrame.bottom); + ok(asi1.dwEditCount == 0, "got %u (expected 0)\n", asi1.dwEditCount); + ok(asi1.dwFormatChangeCount == 0, "got %u (expected 0)\n)", asi1.dwFormatChangeCount); + + ok(wfx.wFormatTag == 1, "got %u (expected 1)\n",wfx.wFormatTag); + ok(wfx.nChannels == 2, "got %u (expected 2)\n",wfx.nChannels); + ok(wfx.wFormatTag == 1, "got %u (expected 1)\n",wfx.wFormatTag); + ok(wfx.nSamplesPerSec == 11025, "got %u (expected 11025)\n",wfx.nSamplesPerSec); + ok(wfx.nAvgBytesPerSec == 22050, "got %u (expected 22050)\n",wfx.nAvgBytesPerSec); + ok(wfx.nBlockAlign == 2, "got %u (expected 2)\n",wfx.nBlockAlign); + + AVIStreamRelease(pStream0); + AVIStreamRelease(pStream1); + AVIFileRelease(pFile); + ok(DeleteFile("small.avi") !=0, "Deleting file small.avi failed"); +} + +static void test_ash1_corruption(void) { + COMMON_AVI_HEADERS cah; + PAVIFILE pFile; + int res; + PAVISTREAM pStream1; + AVISTREAMINFO asi1; + + init_test_struct(&cah); + + /* Corrupt the sample size in the audio stream header */ + cah.ash1.dwSampleSize = 0xdeadbeef; + + create_avi_file(&cah); + + res = AVIFileOpen(&pFile, "small.avi", OF_SHARE_DENY_WRITE, 0L); + ok(res == 0, "Unable to open file: error=%u\n", res); + + res = AVIFileGetStream(pFile, &pStream1, 0, 1); + ok(res == 0, "Unable to open audio stream: error=%u\n", res); + + res = AVIStreamInfo(pStream1, &asi1, sizeof(AVISTREAMINFO)); + ok(res == 0, "Unable to read stream info: error=%u\n", res); + + /* The result will still be 2, because the value is dynamically replaced with the nBlockAlign + value from the stream format header. The next test will prove this */ + ok(asi1.dwSampleSize == 2, "got %u (expected 2)\n", asi1.dwSampleSize); + + AVIStreamRelease(pStream1); + AVIFileRelease(pFile); + ok(DeleteFile("small.avi") !=0, "Deleting file small.avi failed"); +} + +static void test_ash1_corruption2(void) { + COMMON_AVI_HEADERS cah; + PAVIFILE pFile; + int res; + PAVISTREAM pStream1; + AVISTREAMINFO asi1; + + init_test_struct(&cah); + + /* Corrupt the block alignment in the audio format header */ + cah.pcmwf.wf.nBlockAlign = 0xdead; + + create_avi_file(&cah); + + res = AVIFileOpen(&pFile, "small.avi", OF_SHARE_DENY_WRITE, 0L); + ok(res == 0, "Unable to open file: error=%u\n", res); + + res = AVIFileGetStream(pFile, &pStream1, 0, 1); + ok(res == 0, "Unable to open audio stream: error=%u\n", res); + + ok(AVIStreamInfo(pStream1, &asi1, sizeof(AVISTREAMINFO)) == 0, "Unable to read stream info\n"); + + /* The result will also be the corrupt value, as explained above. */ + ok(asi1.dwSampleSize == 0xdead, "got %u (expected 0xdead)\n", asi1.dwSampleSize); + + AVIStreamRelease(pStream1); + AVIFileRelease(pFile); + ok(DeleteFile("small.avi") !=0, "Deleting file small.avi failed"); +} + +/* ########################### */ + START_TEST(api) {
AVIFileInit(); test_AVISaveOptions(); + test_default_data(); + test_ash1_corruption(); + test_ash1_corruption2(); AVIFileExit();
}
Julius Schwartzenberg wrote:
+static void init_test_struct(COMMON_AVI_HEADERS *cah) +{
- memcpy(&cah->mah, &defmah, sizeof(defmah));
- memcpy(&cah->ash0, &defash0, sizeof(defash0));
- memcpy(&cah->ash1, &defash1, sizeof(defash1));
- memcpy(&cah->pcmwf, &defpcmwf, sizeof(defpcmwf));
+}
You don't need to use memcpy to copy structures. Simple assignment is enough. Eg: cah->mah = defmah;
+static void create_avi_file(const COMMON_AVI_HEADERS *cah) +{
- HANDLE hFile;
- DWORD written;
- hFile = CreateFile("small.avi", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
For tests you should always specify full path. Here you probably want to get system's tmp directory.
+static void test_default_data(void) +{
- res = AVIFileOpen(&pFile, "small.avi", OF_SHARE_DENY_WRITE, 0L);
Same thing here.
Vitaliy.
Hi Vitaliy,
Thanks a lot for your feedback!
Vitaliy Margolen wrote:
Julius Schwartzenberg wrote: You don't need to use memcpy to copy structures. Simple assignment is enough. Eg: cah->mah = defmah;
I didn't know that. I fixed it now here :)
For tests you should always specify full path. Here you probably want to get system's tmp directory.
I understand I need to use the GetTempFileName and GetTempPath functions for this. I'll solve this too. Since I will probably have to resend the patch, I'll be sure to include your suggestions then!
Regards, Julius