[KERNEL32]
[reactos.git] / rostests / apitests / apitest.c
1 #include "apitest.h"
2
3 const char szFileHeader1[] = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"
4 "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n"
5 "<head>\n"
6 "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n";
7 const char szFileHeader2[] = "<style type=\"text/css\">\n"
8 "body {font-family: sans-serif;}\n"
9 "table {width: 100%;}\n"
10 "th {text-align: left;}\n"
11 "td.red {color: red;}\n"
12 "td.green {color: green;}\n"
13 "</style>\n"
14 "</head>\n"
15 "<body>\n";
16 const char szTableHeader[] = "<table><tr><th>Function</th><th>Status</th><th>Tests (all/passed/failed)</th><th>Regressions</th></tr>";
17 const char szFileFooter[] = "</table></body></html>";
18
19 void
20 OutputUsage(LPWSTR pszName)
21 {
22 printf("\nUsage:\n\n");
23 printf("%ls.exe <TestName> - Perform individual test\n", pszName);
24 printf("%ls.exe all - Perform all tests\n", pszName);
25 printf("%ls.exe tests - List the valid test names\n", pszName);
26 printf("%ls.exe status - Create api status file\n", pszName);
27 printf("%ls.exe -r ... - Perform regression testing\n", pszName);
28 printf("\n");
29 }
30
31 BOOL
32 WriteFileHeader(HANDLE hFile, LPDWORD lpdwBytesWritten, LPWSTR pszModule)
33 {
34 char szHeader[100];
35
36 WriteFile(hFile, szFileHeader1, strlen(szFileHeader1), lpdwBytesWritten, NULL);
37 sprintf(szHeader, "<title>%ls Test results</title>", pszModule);
38 WriteFile(hFile, szHeader, strlen(szHeader), lpdwBytesWritten, NULL);
39 WriteFile(hFile, szFileHeader2, strlen(szFileHeader2), lpdwBytesWritten, NULL);
40
41 sprintf(szHeader, "<h1>Test results for %ls</h1>", pszModule);
42 WriteFile(hFile, szHeader, strlen(szHeader), lpdwBytesWritten, NULL);
43
44 WriteFile(hFile, szTableHeader, strlen(szTableHeader), lpdwBytesWritten, NULL);
45
46 return TRUE;
47 }
48
49 BOOL
50 WriteRow(HANDLE hFile, LPDWORD lpdwBytesWritten, LPWSTR pszFunction, PTESTINFO pti)
51 {
52 char szLine[500];
53
54 sprintf(szLine, "<tr><td>%ls</td>", pszFunction);
55
56 switch(pti->nApiStatus)
57 {
58 case APISTATUS_NOT_FOUND:
59 strcat(szLine, "<td class=\"red\">not found</td>");
60 break;
61 case APISTATUS_UNIMPLEMENTED:
62 strcat(szLine, "<td class=\"red\">unimplemented</td>");
63 break;
64 case APISTATUS_ASSERTION_FAILED:
65 strcat(szLine, "<td class=\"red\">assertion failed</td>");
66 break;
67 case APISTATUS_REGRESSION:
68 strcat(szLine, "<td class=\"red\">Regression!</td>");
69 break;
70 case APISTATUS_NORMAL:
71 strcat(szLine, "<td class=\"green\">Implemented</td>");
72 break;
73 }
74
75 sprintf(szLine + strlen(szLine), "<td>%d / %d / %d</td><td>%d</td></tr>\n",
76 pti->passed+pti->failed, pti->passed, pti->failed, pti->rfailed);
77
78 WriteFile(hFile, szLine, strlen(szLine), lpdwBytesWritten, NULL);
79
80 return TRUE;
81 }
82
83 static CHAR
84 GetDisplayChar(CHAR c)
85 {
86 if (c < 32) return '.';
87 return c;
88 }
89
90 VOID
91 DumpMem(PVOID pData, ULONG cbSize, ULONG nWidth)
92 {
93 ULONG cLines = (cbSize + nWidth - 1) / nWidth;
94 ULONG cbLastLine = cbSize % nWidth;
95 INT i,j;
96
97 for (i = 0; i <= cLines; i++)
98 {
99 printf("%08lx: ", i*nWidth);
100 for (j = 0; j < (i == cLines? cbLastLine : nWidth); j++)
101 {
102 printf("%02x ", ((BYTE*)pData)[i*nWidth + j]);
103 }
104 printf(" ");
105 for (j = 0; j < (i == cLines? cbLastLine : nWidth); j++)
106 {
107 printf("%c", GetDisplayChar(((CHAR*)pData)[i*nWidth + j]));
108 }
109 printf("\n");
110 }
111 }
112
113 int
114 TestMain(LPWSTR pszName, LPWSTR pszModule)
115 {
116 INT argc, i, j;
117 LPWSTR *argv;
118 TESTINFO ti;
119 INT opassed, ofailed, orfailed;
120 BOOL bAll, bStatus;
121 HANDLE hFile = NULL;
122 DWORD dwBytesWritten;
123
124 ti.bRegress = FALSE;
125 bAll = FALSE;
126 bStatus = FALSE;
127 opassed = ofailed = orfailed = 0;
128
129 argv = CommandLineToArgvW(GetCommandLineW(), &argc);
130
131 if (argc < 2)
132 {
133 OutputUsage(pszName);
134 return 0;
135 }
136
137 /* Get options */
138 for (i = 1; i < argc; i++)
139 {
140 if (_wcsicmp(argv[i], L"-r") == 0)
141 {
142 ti.bRegress = TRUE;
143 }
144 else if (_wcsicmp(argv[i], L"all") == 0)
145 {
146 bAll = TRUE;
147 }
148 else if (_wcsicmp(argv[i], L"status") == 0)
149 {
150 bAll = TRUE;
151 bStatus = TRUE;
152 }
153 else if (_wcsicmp(argv[i], L"tests") == 0)
154 {
155 /* List all the tests and exit */
156 printf("Valid test names:\n\n");
157
158 for (i = 0; i < NumTests(); i++)
159 printf("%ls\n", TestList[i].Test);
160
161 return 0;
162 }
163 }
164
165 if (bStatus)
166 {
167 WCHAR szOutputFile[MAX_PATH];
168
169 ti.bRegress = TRUE;
170 wcscpy(szOutputFile, pszName);
171 wcscat(szOutputFile, L".html");
172 hFile = CreateFileW(szOutputFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
173
174 if (hFile == INVALID_HANDLE_VALUE)
175 {
176 printf("Could not create output file.\n");
177 return 0;
178 }
179
180 WriteFileHeader(hFile, &dwBytesWritten, pszModule);
181 }
182
183 for (i = 0; i < NumTests(); i++)
184 {
185 for (j = 1; j < argc; j++)
186 {
187 if (bAll || _wcsicmp(argv[j], TestList[i].Test) == 0)
188 {
189 ti.passed = 0;
190 ti.failed = 0;
191 ti.rfailed = 0;
192 if (!IsFunctionPresent(TestList[i].Test))
193 {
194 printf("Function %ls was not found!\n", TestList[i].Test);
195 ti.nApiStatus = APISTATUS_NOT_FOUND;
196 }
197 else
198 {
199 printf("Executing test: %ls\n", TestList[i].Test);
200 ti.nApiStatus = TestList[i].Proc(&ti);
201 opassed += ti.passed;
202 ofailed += ti.failed;
203 orfailed += ti.rfailed;
204 printf(" tests: %d, passed: %d, failed: %d\n\n", ti.passed+ti.failed, ti.passed, ti.failed);
205 }
206 if (bStatus)
207 {
208 if (ti.rfailed > 0)
209 ti.nApiStatus = APISTATUS_REGRESSION;
210 WriteRow(hFile, &dwBytesWritten, TestList[i].Test, &ti);
211 }
212 break;
213 }
214 }
215 }
216
217 printf("Overall:\n");
218 printf(" tests: %d, passed: %d, failed: %d\n\n", opassed+ofailed, opassed, ofailed);
219 if (ti.bRegress)
220 {
221 printf(" regressions: %d\n", orfailed);
222 }
223
224 if (bStatus)
225 {
226 WriteFile(hFile, szFileFooter, strlen(szFileFooter), &dwBytesWritten, NULL);
227 CloseHandle(hFile);
228 }
229
230 if (ti.bRegress)
231 return ti.rfailed;
232
233 return ti.failed;
234 }