diff --git a/dlls/winmm/tests/.cvsignore b/dlls/winmm/tests/.cvsignore index e4f9982e478..5e5f8e4c265 100644 --- a/dlls/winmm/tests/.cvsignore +++ b/dlls/winmm/tests/.cvsignore @@ -2,4 +2,5 @@ Makefile capture.ok mixer.ok testlist.c +timer.ok wave.ok diff --git a/dlls/winmm/tests/Makefile.in b/dlls/winmm/tests/Makefile.in index eec41ba14a9..28774f328c4 100644 --- a/dlls/winmm/tests/Makefile.in +++ b/dlls/winmm/tests/Makefile.in @@ -8,6 +8,7 @@ IMPORTS = winmm kernel32 CTESTS = \ capture.c \ mixer.c \ + timer.c \ wave.c @MAKE_TEST_RULES@ diff --git a/dlls/winmm/tests/timer.c b/dlls/winmm/tests/timer.c new file mode 100644 index 00000000000..e48ef03d783 --- /dev/null +++ b/dlls/winmm/tests/timer.c @@ -0,0 +1,163 @@ +/* + * Test winmm timer + * + * Copyright (c) 2005 Robert Reif + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "wine/test.h" +#include "windef.h" +#include "winbase.h" +#include "winnls.h" +#include "mmsystem.h" +#define NOBITMAP +#include "mmreg.h" + +#include "winmm_test.h" + +TIMECAPS tc; + +void test_timeGetDevCaps() +{ + MMRESULT rc; + + rc = timeGetDevCaps(&tc, 0); + ok(rc == TIMERR_NOCANDO, "timeGetDevCaps() returned %s, " + "should have returned TIMERR_NOCANDO\n", mmsys_error(rc)); + + rc = timeGetDevCaps(0, sizeof(tc)); + ok(rc == TIMERR_NOCANDO, "timeGetDevCaps() returned %s, " + "should have returned TIMERR_NOCANDO\n", mmsys_error(rc)); + + rc = timeGetDevCaps(0, 0); + ok(rc == TIMERR_NOCANDO, "timeGetDevCaps() returned %s, " + "should have returned TIMERR_NOCANDO\n", mmsys_error(rc)); + + rc = timeGetDevCaps(&tc, sizeof(tc)); + ok(rc == TIMERR_NOERROR, "timeGetDevCaps() returned %s, " + "should have returned TIMERR_NOERROR\n", mmsys_error(rc)); + + if (rc == TIMERR_NOERROR) + trace("wPeriodMin = %u, wPeriodMax = %u\n", + tc.wPeriodMin, tc.wPeriodMax); +} + +#define NUM_SAMPLES 100 + +static DWORD count = 0; +static DWORD times[NUM_SAMPLES]; + +void CALLBACK testTimeProc(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) +{ + if (count < NUM_SAMPLES) + times[count++] = timeGetTime(); +} + +void test_timer(UINT period, UINT resolution) +{ + MMRESULT rc; + UINT i, id, delta; + DWORD dwMin = 0xffffffff, dwMax = 0; + double sum = 0.0; + double deviation = 0.0; + + count = 0; + + for (i = 0; i < NUM_SAMPLES; i++) + times[i] = 0; + + rc = timeBeginPeriod(period); + ok(rc == TIMERR_NOERROR, "timeBeginPeriod(%u) returned %s, " + "should have returned TIMERR_NOERROR", period, mmsys_error(rc)); + if (rc != TIMERR_NOERROR) + return; + + id = timeSetEvent(period, resolution, testTimeProc, 0, TIME_PERIODIC); + ok(id != 0, "timeSetEvent(%u, %u, %p, 0, TIME_PERIODIC) returned %d, " + "should have returned id > 0", period, resolution, testTimeProc, id); + if (id == 0) + return; + + Sleep((NUM_SAMPLES * period) + (2 * period)); + + rc = timeEndPeriod(period); + ok(rc == TIMERR_NOERROR, "timeEndPeriod(%u) returned %s, " + "should have returned TIMERR_NOERROR", period, mmsys_error(rc)); + if (rc != TIMERR_NOERROR) + return; + + rc = timeKillEvent(id); + ok(rc == TIMERR_NOERROR, "timeKillEvent(%u) returned %s, " + "should have returned TIMERR_NOERROR", id, mmsys_error(rc)); + + trace("period = %u, resolution = %u\n", period, resolution); + + for (i = 0; i < count; i++) + { + if (i == 0) + { + if (winetest_debug > 1) + trace("time[%d] = %lu\n", i, times[i]); + } + else + { + delta = times[i] - times[i - 1]; + + if (winetest_debug > 1) + trace("time[%d] = %lu delta = %d\n", i, times[i], delta); + + sum += delta; + deviation = deviation + ((delta - period) * (delta - period)); + + if (delta < dwMin) + dwMin = delta; + + if (delta > dwMax) + dwMax = delta; + } + } + + trace("min = %lu, max = %lu, average = %f, standard deviation = %f\n", + dwMin, dwMax, sum / (count - 1), sqrt(deviation / (count - 2))); +} + +START_TEST(timer) +{ + test_timeGetDevCaps(); + + if (tc.wPeriodMin <= 1) { + test_timer(1, 0); + test_timer(1, 1); + } + + if (tc.wPeriodMin <= 10) { + test_timer(10, 0); + test_timer(10, 1); + test_timer(10, 10); + } + + if (tc.wPeriodMin <= 20) { + test_timer(20, 0); + test_timer(20, 1); + test_timer(20, 10); + test_timer(20, 20); + } +} diff --git a/dlls/winmm/time.c b/dlls/winmm/time.c index 16d9c909be9..a1960ce919d 100644 --- a/dlls/winmm/time.c +++ b/dlls/winmm/time.c @@ -408,9 +408,19 @@ MMRESULT WINAPI timeGetDevCaps(LPTIMECAPS lpCaps, UINT wSize) { TRACE("(%p, %u)\n", lpCaps, wSize); + if (lpCaps == 0) { + WARN("invalid lpCaps\n"); + return TIMERR_NOCANDO; + } + + if (wSize < sizeof(TIMECAPS)) { + WARN("invalid wSize\n"); + return TIMERR_NOCANDO; + } + lpCaps->wPeriodMin = MMSYSTIME_MININTERVAL; lpCaps->wPeriodMax = MMSYSTIME_MAXINTERVAL; - return 0; + return TIMERR_NOERROR; } /**************************************************************************