[RFC PATCH v3 1/2] ntdll/tests: Test updating TickCount in user_shared_data.

Zebediah Figura zfigura at codeweavers.com
Tue Apr 28 11:30:28 CDT 2020


On 4/28/20 10:11 AM, Rémi Bernon wrote:
> Original patch from: Andrew Wesie <awesie at gmail.com>
> 
> Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
> ---
> 
> v3: Server-side implementation of USD timestamp updates.
> 
>    The system time check still has some large diffs compared to native
>    after patch #2, probably because of some different clock granularity
>    between server and client.
> 
>    I didn't include an InterruptTime test because depending on the
>    Windows versions, RtlQueryUnbiasedInterruptTime sometimes doesn't
>    match the USD clock.
> 
>    I'm sending it as RFC as it's still a little bit rough on the edges,
>    and I only tested on Linux so far.
> 
>   dlls/ntdll/tests/time.c | 52 +++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 52 insertions(+)
> 
> diff --git a/dlls/ntdll/tests/time.c b/dlls/ntdll/tests/time.c
> index 5382a952d8d8..cc6e9f226e63 100644
> --- a/dlls/ntdll/tests/time.c
> +++ b/dlls/ntdll/tests/time.c
> @@ -18,7 +18,9 @@
>    * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
>    */
>   
> +#define NONAMELESSUNION
>   #include "ntdll_test.h"
> +#include "ddk/wdm.h"
>   
>   #define TICKSPERSEC        10000000
>   #define TICKSPERMSEC       10000
> @@ -29,6 +31,7 @@ static VOID (WINAPI *pRtlTimeFieldsToTime)(  PTIME_FIELDS TimeFields,  PLARGE_IN
>   static NTSTATUS (WINAPI *pNtQueryPerformanceCounter)( LARGE_INTEGER *counter, LARGE_INTEGER *frequency );
>   static NTSTATUS (WINAPI *pRtlQueryTimeZoneInformation)( RTL_TIME_ZONE_INFORMATION *);
>   static NTSTATUS (WINAPI *pRtlQueryDynamicTimeZoneInformation)( RTL_DYNAMIC_TIME_ZONE_INFORMATION *);
> +static ULONG (WINAPI *pNtGetTickCount)(void);
>   
>   static const int MonthLengths[2][12] =
>   {
> @@ -153,12 +156,60 @@ static void test_RtlQueryTimeZoneInformation(void)
>          wine_dbgstr_w(tzinfo.DaylightName));
>   }
>   
> +static ULONG64 read_ksystem_time(volatile KSYSTEM_TIME *time)
> +{
> +    ULONG64 high, low;
> +
> +    do
> +    {
> +        high = time->High1Time;
> +        low = time->LowPart;
> +    }
> +    while (high != time->High2Time);
> +
> +    return high << 32 | low;
> +}
> +
> +static void test_NtGetTickCount(void)
> +{
> +    KSHARED_USER_DATA *user_shared_data = (void *)0x7ffe0000;
> +    ULONG64 usd_time;
> +    ULONG diff;
> +    int i;
> +
> +    for (i = 0; i < 5; ++i)
> +    {
> +        LARGE_INTEGER system_time;
> +
> +        if (user_shared_data->NtMajorVersion <= 5 && user_shared_data->NtMinorVersion <= 1)
> +            usd_time = ((ULONG64)user_shared_data->TickCountLowDeprecated * user_shared_data->TickCountMultiplier) >> 24;
> +        else
> +            usd_time = (read_ksystem_time(&user_shared_data->u.TickCount) * user_shared_data->TickCountMultiplier) >> 24;
> +
> +        if (!pNtGetTickCount)
> +            diff = GetTickCount() - usd_time;
> +        else
> +            diff = pNtGetTickCount() - usd_time;

We already have tests in kernel32 that GetTickCount() and 
NtGetTickCount() are close, so it seems probably easiest to just test 
GetTickCount() here.

> +        todo_wine
> +        ok(diff < 100, "NtGetTickCount - USD->TickCount too high, expected < 100 got %d\n", diff);
> +
> +        usd_time = read_ksystem_time(&user_shared_data->SystemTime);
> +        NtQuerySystemTime(&system_time);
> +        diff = system_time.QuadPart - usd_time;
> +        todo_wine
> +        ok(diff < 100, "NtQuerySystemTime - USD->SystemTime too high, expected < 100 got %d\n", diff);
> +

The way it's done in kernel32() is to read from sources A, B, A, then 
check that A < B < A. Assuming that source A is sane, that lets you 
avoid any failures due to spurious lag (as is unfortunately often the 
case with the testbot.)

> +        Sleep(50);
> +    }
> +}
> +
>   START_TEST(time)
>   {
>       HMODULE mod = GetModuleHandleA("ntdll.dll");
>       pRtlTimeToTimeFields = (void *)GetProcAddress(mod,"RtlTimeToTimeFields");
>       pRtlTimeFieldsToTime = (void *)GetProcAddress(mod,"RtlTimeFieldsToTime");
>       pNtQueryPerformanceCounter = (void *)GetProcAddress(mod, "NtQueryPerformanceCounter");
> +    pNtGetTickCount = (void *)GetProcAddress(mod,"NtGetTickCount");
>       pRtlQueryTimeZoneInformation =
>           (void *)GetProcAddress(mod, "RtlQueryTimeZoneInformation");
>       pRtlQueryDynamicTimeZoneInformation =
> @@ -169,5 +220,6 @@ START_TEST(time)
>       else
>           win_skip("Required time conversion functions are not available\n");
>       test_NtQueryPerformanceCounter();
> +    test_NtGetTickCount();
>       test_RtlQueryTimeZoneInformation();
>   }
> 




More information about the wine-devel mailing list