7d9e65148e35d6094de96a843ec92697716db5f2
[reactos.git] / modules / rostests / winetests / ntdll / time.c
1 /*
2 * Unit test suite for ntdll time functions
3 *
4 * Copyright 2004 Rein Klazes
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include "ntdll_test.h"
22
23 /* FIXME: Inspect */
24
25 typedef struct _KSYSTEM_TIME {
26 ULONG LowPart;
27 LONG High1Time;
28 LONG High2Time;
29 } KSYSTEM_TIME, *PKSYSTEM_TIME;
30
31 typedef enum _NT_PRODUCT_TYPE {
32 NtProductWinNt = 1,
33 NtProductLanManNt,
34 NtProductServer
35 } NT_PRODUCT_TYPE, *PNT_PRODUCT_TYPE;
36
37 #define PROCESSOR_FEATURE_MAX 64
38
39 typedef enum _ALTERNATIVE_ARCHITECTURE_TYPE
40 {
41 StandardDesign,
42 NEC98x86,
43 EndAlternatives
44 } ALTERNATIVE_ARCHITECTURE_TYPE;
45
46 #define MAX_WOW64_SHARED_ENTRIES 16
47
48 typedef struct _KUSER_SHARED_DATA {
49 ULONG TickCountLowDeprecated;
50 ULONG TickCountMultiplier;
51 volatile KSYSTEM_TIME InterruptTime;
52 volatile KSYSTEM_TIME SystemTime;
53 volatile KSYSTEM_TIME TimeZoneBias;
54 USHORT ImageNumberLow;
55 USHORT ImageNumberHigh;
56 WCHAR NtSystemRoot[260];
57 ULONG MaxStackTraceDepth;
58 ULONG CryptoExponent;
59 ULONG TimeZoneId;
60 ULONG LargePageMinimum;
61 ULONG Reserved2[7];
62 NT_PRODUCT_TYPE NtProductType;
63 BOOLEAN ProductTypeIsValid;
64 ULONG NtMajorVersion;
65 ULONG NtMinorVersion;
66 BOOLEAN ProcessorFeatures[PROCESSOR_FEATURE_MAX];
67 ULONG Reserved1;
68 ULONG Reserved3;
69 volatile ULONG TimeSlip;
70 ALTERNATIVE_ARCHITECTURE_TYPE AlternativeArchitecture;
71 LARGE_INTEGER SystemExpirationDate;
72 ULONG SuiteMask;
73 BOOLEAN KdDebuggerEnabled;
74 UCHAR NXSupportPolicy;
75 volatile ULONG ActiveConsoleId;
76 volatile ULONG DismountCount;
77 ULONG ComPlusPackage;
78 ULONG LastSystemRITEventTickCount;
79 ULONG NumberOfPhysicalPages;
80 BOOLEAN SafeBootMode;
81 ULONG TraceLogging;
82 ULONGLONG TestRetInstruction;
83 ULONG SystemCall;
84 ULONG SystemCallReturn;
85 ULONGLONG SystemCallPad[3];
86 union {
87 volatile KSYSTEM_TIME TickCount;
88 volatile ULONG64 TickCountQuad;
89 } DUMMYUNIONNAME;
90 ULONG Cookie;
91 ULONG Wow64SharedInformation[MAX_WOW64_SHARED_ENTRIES];
92 } KSHARED_USER_DATA, *PKSHARED_USER_DATA;
93
94 #define TICKSPERSEC 10000000
95 #define TICKSPERMSEC 10000
96 #define SECSPERDAY 86400
97
98 static VOID (WINAPI *pRtlTimeToTimeFields)( const LARGE_INTEGER *liTime, PTIME_FIELDS TimeFields) ;
99 static VOID (WINAPI *pRtlTimeFieldsToTime)( PTIME_FIELDS TimeFields, PLARGE_INTEGER Time) ;
100 static NTSTATUS (WINAPI *pNtQueryPerformanceCounter)( LARGE_INTEGER *counter, LARGE_INTEGER *frequency );
101 static ULONG (WINAPI *pNtGetTickCount)(void);
102
103 static const int MonthLengths[2][12] =
104 {
105 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
106 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
107 };
108
109 static inline BOOL IsLeapYear(int Year)
110 {
111 return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0);
112 }
113
114 /* start time of the tests */
115 static TIME_FIELDS tftest = {1889,12,31,23,59,59,0,0};
116
117 static void test_pRtlTimeToTimeFields(void)
118 {
119 LARGE_INTEGER litime , liresult;
120 TIME_FIELDS tfresult;
121 int i=0;
122 litime.QuadPart = ((ULONGLONG)0x0144017a << 32) | 0xf0b0a980;
123 while( tftest.Year < 2110 ) {
124 /* test at the last second of the month */
125 pRtlTimeToTimeFields( &litime, &tfresult);
126 ok( tfresult.Year == tftest.Year && tfresult.Month == tftest.Month &&
127 tfresult.Day == tftest.Day && tfresult.Hour == tftest.Hour &&
128 tfresult.Minute == tftest.Minute && tfresult.Second == tftest.Second,
129 "#%d expected: %d-%d-%d %d:%d:%d got: %d-%d-%d %d:%d:%d\n", ++i,
130 tftest.Year, tftest.Month, tftest.Day,
131 tftest.Hour, tftest.Minute,tftest.Second,
132 tfresult.Year, tfresult.Month, tfresult.Day,
133 tfresult.Hour, tfresult.Minute, tfresult.Second);
134 /* test the inverse */
135 pRtlTimeFieldsToTime( &tfresult, &liresult);
136 ok( liresult.QuadPart == litime.QuadPart," TimeFieldsToTime failed on %d-%d-%d %d:%d:%d. Error is %d ticks\n",
137 tfresult.Year, tfresult.Month, tfresult.Day,
138 tfresult.Hour, tfresult.Minute, tfresult.Second,
139 (int) (liresult.QuadPart - litime.QuadPart) );
140 /* one second later is beginning of next month */
141 litime.QuadPart += TICKSPERSEC ;
142 pRtlTimeToTimeFields( &litime, &tfresult);
143 ok( tfresult.Year == tftest.Year + (tftest.Month ==12) &&
144 tfresult.Month == tftest.Month % 12 + 1 &&
145 tfresult.Day == 1 && tfresult.Hour == 0 &&
146 tfresult.Minute == 0 && tfresult.Second == 0,
147 "#%d expected: %d-%d-%d %d:%d:%d got: %d-%d-%d %d:%d:%d\n", ++i,
148 tftest.Year + (tftest.Month ==12),
149 tftest.Month % 12 + 1, 1, 0, 0, 0,
150 tfresult.Year, tfresult.Month, tfresult.Day,
151 tfresult.Hour, tfresult.Minute, tfresult.Second);
152 /* test the inverse */
153 pRtlTimeFieldsToTime( &tfresult, &liresult);
154 ok( liresult.QuadPart == litime.QuadPart," TimeFieldsToTime failed on %d-%d-%d %d:%d:%d. Error is %d ticks\n",
155 tfresult.Year, tfresult.Month, tfresult.Day,
156 tfresult.Hour, tfresult.Minute, tfresult.Second,
157 (int) (liresult.QuadPart - litime.QuadPart) );
158 /* advance to the end of the month */
159 litime.QuadPart -= TICKSPERSEC ;
160 if( tftest.Month == 12) {
161 tftest.Month = 1;
162 tftest.Year += 1;
163 } else
164 tftest.Month += 1;
165 tftest.Day = MonthLengths[IsLeapYear(tftest.Year)][tftest.Month - 1];
166 litime.QuadPart += (LONGLONG) tftest.Day * TICKSPERSEC * SECSPERDAY;
167 }
168 }
169
170 static void test_NtQueryPerformanceCounter(void)
171 {
172 LARGE_INTEGER counter, frequency;
173 NTSTATUS status;
174
175 status = pNtQueryPerformanceCounter(NULL, NULL);
176 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %08x\n", status);
177 status = pNtQueryPerformanceCounter(NULL, &frequency);
178 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %08x\n", status);
179 status = pNtQueryPerformanceCounter(&counter, (void *)0xdeadbee0);
180 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %08x\n", status);
181 status = pNtQueryPerformanceCounter((void *)0xdeadbee0, &frequency);
182 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %08x\n", status);
183
184 status = pNtQueryPerformanceCounter(&counter, NULL);
185 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
186 status = pNtQueryPerformanceCounter(&counter, &frequency);
187 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
188 }
189
190 static void test_NtGetTickCount(void)
191 {
192 #ifndef _WIN64
193 KSHARED_USER_DATA *user_shared_data = (void *)0x7ffe0000;
194 LONG diff;
195 int i;
196
197 if (!pNtGetTickCount)
198 {
199 win_skip("NtGetTickCount is not available\n");
200 return;
201 }
202
203 for (i = 0; i < 5; ++i)
204 {
205 diff = (user_shared_data->TickCountQuad * user_shared_data->TickCountMultiplier) >> 24;
206 diff = pNtGetTickCount() - diff;
207 ok(diff < 32, "NtGetTickCount - TickCountQuad too high, expected < 32 got %d\n", diff);
208 Sleep(50);
209 }
210 #endif
211 }
212
213 START_TEST(time)
214 {
215 HMODULE mod = GetModuleHandleA("ntdll.dll");
216 pRtlTimeToTimeFields = (void *)GetProcAddress(mod,"RtlTimeToTimeFields");
217 pRtlTimeFieldsToTime = (void *)GetProcAddress(mod,"RtlTimeFieldsToTime");
218 pNtQueryPerformanceCounter = (void *)GetProcAddress(mod, "NtQueryPerformanceCounter");
219 pNtGetTickCount = (void *)GetProcAddress(mod,"NtGetTickCount");
220 if (pRtlTimeToTimeFields && pRtlTimeFieldsToTime)
221 test_pRtlTimeToTimeFields();
222 else
223 win_skip("Required time conversion functions are not available\n");
224 test_NtQueryPerformanceCounter();
225 test_NtGetTickCount();
226 }