Reactos
1/*
2 * PROJECT: ReactOS Automatic Testing Utility
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Main implementation file
5 * COPYRIGHT: Copyright 2008-2009 Colin Finck (colin@reactos.org)
6 */
7
8#include "precomp.h"
9#include <cstdio>
10#include <ndk/setypes.h>
11#include <ndk/exfuncs.h>
12
13WCHAR TestName[MAX_PATH];
14
15CConfiguration Configuration;
16
17/**
18 * Prints the application usage.
19 */
20static void
21IntPrintUsage()
22{
23 cout << "rosautotest - ReactOS Automatic Testing Utility" << endl
24 << "Usage: rosautotest [options] [module] [test]" << endl
25 << " options:" << endl
26 << " /? - Shows this help." << endl
27 << " /c <comment> - Specifies the comment to be submitted to the Web Service." << endl
28 << " Skips the comment set in the configuration file (if any)." << endl
29 << " Only has an effect when /w is also used." << endl
30 << " /n - Do not print test output to console" << endl
31 << " /r - Maintain information to resume from ReactOS crashes" << endl
32 << " Can only be run under ReactOS and relies on sysreg2," << endl
33 << " so incompatible with /w" << endl
34 << " /s - Shut down the system after finishing the tests." << endl
35 << " /t <num> - Repeat the test <num> times (1-10000)" << endl
36 << " /w - Submit the results to the webservice." << endl
37 << " Requires a \"rosautotest.ini\" with valid login data." << endl
38 << " Incompatible with the /r option." << endl
39 << " /l - List all modules that would run." << endl
40 << endl
41 << " module:" << endl
42 << " The module to be tested (i.e. \"advapi32\")" << endl
43 << " If this parameter is specified without any test parameter," << endl
44 << " all tests of the specified module are run." << endl
45 << endl
46 << " test:" << endl
47 << " The test to be run. Needs to be a test of the specified module." << endl;
48}
49
50static
51VOID
52SetNtGlobalFlags()
53{
54 ULONG NtGlobalFlags = 0;
55 BOOLEAN PrivilegeEnabled;
56 NTSTATUS Status;
57
58 /* Enable SeDebugPrivilege */
59 Status = RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, TRUE, FALSE, &PrivilegeEnabled);
60 if (!NT_SUCCESS(Status))
61 {
62 DbgPrint("Failed to enable SeDebugPrivilege: 0x%08lx\n", Status);
63 return;
64 }
65
66 /* Get current NtGlobalFlags */
67 Status = NtQuerySystemInformation(SystemFlagsInformation, &NtGlobalFlags, sizeof(NtGlobalFlags), NULL);
68 if (!NT_SUCCESS(Status))
69 {
70 DbgPrint("Failed to get NtGlobalFlags: 0x%08lx\n", Status);
71 return;
72 }
73
74 /* Disable debug prompts */
75 NtGlobalFlags |= FLG_DISABLE_DEBUG_PROMPTS;
76
77 /* Set new NtGlobalFlags */
78 Status = NtSetSystemInformation(SystemFlagsInformation, &NtGlobalFlags, sizeof(NtGlobalFlags));
79 if (!NT_SUCCESS(Status))
80 {
81 DbgPrint("Failed to set NtGlobalFlags: 0x%08lx\n", Status);
82 }
83}
84
85/**
86 * Main entry point
87 */
88extern "C" int
89wmain(int argc, wchar_t* argv[])
90{
91 int ReturnValue = 1;
92 DWORD TestStartTime, TestEndTime;
93
94 GetModuleFileNameW(NULL, TestName, _countof(TestName));
95// printf("Full TestName is '%S'\n", TestName);
96 WCHAR* Name = wcsrchr(TestName, '\\');
97 if (Name)
98 memmove(TestName, Name + 1, (wcslen(Name + 1) + 1) * sizeof(WCHAR));
99// printf("Short TestName is '%S'.\n", TestName);
100
101 SetNtGlobalFlags();
102
103 try
104 {
105 stringstream ss;
106
107 /* Set up the configuration */
108 Configuration.ParseParameters(argc, argv);
109 Configuration.GetSystemInformation();
110 Configuration.GetConfigurationFromFile();
111
112 TestStartTime = GetTickCount();
113 ss << endl
114 << endl
115 << "[ROSAUTOTEST] System uptime " << setprecision(2) << fixed;
116 ss << (float)TestStartTime / 1000 << " seconds" << endl;
117 StringOut(ss.str());
118
119 /* Report tests startup */
120 InitLogs();
121 ReportEventW(hLog,
122 EVENTLOG_INFORMATION_TYPE,
123 0,
124 MSG_TESTS_STARTED,
125 NULL,
126 0,
127 0,
128 NULL,
129 NULL);
130
131 if (Configuration.GetRepeatCount() > 1)
132 {
133 stringstream ss1;
134
135 ss1 << "[ROSAUTOTEST] The test will be repeated " << Configuration.GetRepeatCount() << " times" << endl;
136 StringOut(ss1.str());
137 }
138
139 /* Run the tests */
140 for (unsigned long i = 0; i < Configuration.GetRepeatCount(); i++)
141 {
142 CWineTest WineTest;
143
144 if (Configuration.GetRepeatCount() > 1)
145 {
146 stringstream ss;
147 ss << "[ROSAUTOTEST] Running attempt #" << i+1 << endl;
148 StringOut(ss.str());
149 }
150 WineTest.Run();
151 }
152
153 /* Clear the stringstream */
154 ss.str("");
155 ss.clear();
156
157 /* Show the beginning time again */
158 ss << "[ROSAUTOTEST] System uptime at start was " << setprecision(2) << fixed;
159 ss << (float)TestStartTime / 1000 << " seconds" << endl;
160
161 /* Show the time now so that we can see how long the tests took */
162 TestEndTime = GetTickCount();
163 ss << endl
164 << "[ROSAUTOTEST] System uptime at end was " << setprecision(2) << fixed;
165 ss << ((float)TestEndTime / 1000) << " seconds" << endl;
166 ss << "[ROSAUTOTEST] Duration was " << (float)(TestEndTime - TestStartTime) / (60 * 1000);
167 ss << " minutes" << endl;
168 StringOut(ss.str());
169
170 /* For sysreg2 */
171 DbgPrint("SYSREG_CHECKPOINT:THIRDBOOT_COMPLETE\n");
172
173 ReturnValue = 0;
174 }
175 catch(CInvalidParameterException)
176 {
177 IntPrintUsage();
178 }
179 catch(CSimpleException& e)
180 {
181 stringstream ss;
182
183 // e.GetMessage() must include ending '\n'.
184 ss << "[ROSAUTOTEST] " << e.GetMessage();
185 StringOut(ss.str());
186 }
187 catch(CFatalException& e)
188 {
189 stringstream ss;
190
191 // e.GetMessage() must include ending '\n'.
192 ss << "An exception occured in rosautotest." << endl
193 << "Message: " << e.GetMessage()
194 << "File: " << e.GetFile() << endl
195 << "Line: " << e.GetLine() << endl
196 << "Last Win32 Error: " << GetLastError() << endl;
197 StringOut(ss.str());
198 }
199
200 /* For sysreg2 to notice if rosautotest itself failed */
201 if(ReturnValue == 1)
202 DbgPrint("SYSREG_ROSAUTOTEST_FAILURE\n");
203
204 /* Report successful end of tests */
205 ReportEventW(hLog,
206 EVENTLOG_SUCCESS,
207 0,
208 MSG_TESTS_SUCCESSFUL,
209 NULL,
210 0,
211 0,
212 NULL,
213 NULL);
214 FreeLogs();
215
216 /* Shut down the system if requested, also in case of an exception above */
217 if(Configuration.DoShutdown() && !ShutdownSystem())
218 ReturnValue = 1;
219
220 return ReturnValue;
221}