|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #include <stdio.h> |
|
7 #include <stdlib.h> |
|
8 #include <windows.h> |
|
9 // Support for _setmode |
|
10 #include <fcntl.h> |
|
11 #include <io.h> |
|
12 |
|
13 #include "nsWindowsRestart.cpp" |
|
14 |
|
15 // CommandLineToArgvW may return different values for argv[0] since it contains |
|
16 // the path to the binary that was executed so we prepend an argument that is |
|
17 // quoted with a space to prevent argv[1] being appended to argv[0]. |
|
18 #define DUMMY_ARG1 L"\"arg 1\" " |
|
19 |
|
20 #ifndef MAXPATHLEN |
|
21 # ifdef PATH_MAX |
|
22 # define MAXPATHLEN PATH_MAX |
|
23 # elif defined(MAX_PATH) |
|
24 # define MAXPATHLEN MAX_PATH |
|
25 # elif defined(_MAX_PATH) |
|
26 # define MAXPATHLEN _MAX_PATH |
|
27 # elif defined(CCHMAXPATH) |
|
28 # define MAXPATHLEN CCHMAXPATH |
|
29 # else |
|
30 # define MAXPATHLEN 1024 |
|
31 # endif |
|
32 #endif |
|
33 |
|
34 #define TEST_NAME L"XRE MakeCommandLine" |
|
35 #define MAX_TESTS 100 |
|
36 |
|
37 // Verbose output can be enabled by defining VERBOSE 1 |
|
38 #define VERBOSE 0 |
|
39 |
|
40 // Compares compareCmdLine with the output of MakeCommandLine. This is |
|
41 // accomplished by converting inCmdLine to an argument list with |
|
42 // CommandLineToArgvW and converting it back to a command line with |
|
43 // MakeCommandLine. |
|
44 static int |
|
45 verifyCmdLineCreation(wchar_t *inCmdLine, |
|
46 wchar_t *compareCmdLine, |
|
47 bool passes, int testNum) |
|
48 { |
|
49 int rv = 0; |
|
50 int i; |
|
51 int inArgc; |
|
52 int outArgc; |
|
53 bool isEqual; |
|
54 |
|
55 // When debugging with command lines containing Unicode characters greater |
|
56 // than 255 you can set the mode for stdout to Unicode so the console will |
|
57 // receive the correct characters though it won't display them properly unless |
|
58 // the console's font has been set to one that can display the characters. You |
|
59 // can also redirect the console output to a file that has been saved as Unicode |
|
60 // to view the characters. |
|
61 // _setmode(_fileno(stdout), _O_WTEXT); |
|
62 |
|
63 // Prepend an additional argument to the command line. CommandLineToArgvW |
|
64 // handles argv[0] differently than other arguments since argv[0] is the path |
|
65 // to the binary being executed and MakeCommandLine only handles argv[1] and |
|
66 // larger. |
|
67 wchar_t *inCmdLineNew = (wchar_t *) malloc((wcslen(DUMMY_ARG1) + wcslen(inCmdLine) + 1) * sizeof(wchar_t)); |
|
68 wcscpy(inCmdLineNew, DUMMY_ARG1); |
|
69 wcscat(inCmdLineNew, inCmdLine); |
|
70 LPWSTR *inArgv = CommandLineToArgvW(inCmdLineNew, &inArgc); |
|
71 |
|
72 wchar_t *outCmdLine = MakeCommandLine(inArgc - 1, inArgv + 1); |
|
73 wchar_t *outCmdLineNew = (wchar_t *) malloc((wcslen(DUMMY_ARG1) + wcslen(outCmdLine) + 1) * sizeof(wchar_t)); |
|
74 wcscpy(outCmdLineNew, DUMMY_ARG1); |
|
75 wcscat(outCmdLineNew, outCmdLine); |
|
76 LPWSTR *outArgv = CommandLineToArgvW(outCmdLineNew, &outArgc); |
|
77 |
|
78 if (VERBOSE) { |
|
79 wprintf(L"\n"); |
|
80 wprintf(L"Verbose Output\n"); |
|
81 wprintf(L"--------------\n"); |
|
82 wprintf(L"Input command line : >%s<\n", inCmdLine); |
|
83 wprintf(L"MakeComandLine output: >%s<\n", outCmdLine); |
|
84 wprintf(L"Expected command line: >%s<\n", compareCmdLine); |
|
85 |
|
86 wprintf(L"input argc : %d\n", inArgc - 1); |
|
87 wprintf(L"output argc: %d\n", outArgc - 1); |
|
88 |
|
89 for (i = 1; i < inArgc; ++i) { |
|
90 wprintf(L"input argv[%d] : >%s<\n", i - 1, inArgv[i]); |
|
91 } |
|
92 |
|
93 for (i = 1; i < outArgc; ++i) { |
|
94 wprintf(L"output argv[%d]: >%s<\n", i - 1, outArgv[i]); |
|
95 } |
|
96 wprintf(L"\n"); |
|
97 } |
|
98 |
|
99 isEqual = (inArgc == outArgc); |
|
100 if (!isEqual) { |
|
101 wprintf(L"TEST-%s-FAIL | %s | ARGC Comparison (check %2d)\n", |
|
102 passes ? L"UNEXPECTED" : L"KNOWN", TEST_NAME, testNum); |
|
103 if (passes) { |
|
104 rv = 1; |
|
105 } |
|
106 LocalFree(inArgv); |
|
107 LocalFree(outArgv); |
|
108 free(inCmdLineNew); |
|
109 free(outCmdLineNew); |
|
110 free(outCmdLine); |
|
111 return rv; |
|
112 } |
|
113 |
|
114 for (i = 1; i < inArgc; ++i) { |
|
115 isEqual = (wcscmp(inArgv[i], outArgv[i]) == 0); |
|
116 if (!isEqual) { |
|
117 wprintf(L"TEST-%s-FAIL | %s | ARGV Comparison (check %2d)\n", |
|
118 passes ? L"UNEXPECTED" : L"KNOWN", TEST_NAME, testNum); |
|
119 if (passes) { |
|
120 rv = 1; |
|
121 } |
|
122 LocalFree(inArgv); |
|
123 LocalFree(outArgv); |
|
124 free(inCmdLineNew); |
|
125 free(outCmdLineNew); |
|
126 free(outCmdLine); |
|
127 return rv; |
|
128 } |
|
129 } |
|
130 |
|
131 isEqual = (wcscmp(outCmdLine, compareCmdLine) == 0); |
|
132 if (!isEqual) { |
|
133 wprintf(L"TEST-%s-FAIL | %s | Command Line Comparison (check %2d)\n", |
|
134 passes ? L"UNEXPECTED" : L"KNOWN", TEST_NAME, testNum); |
|
135 if (passes) { |
|
136 rv = 1; |
|
137 } |
|
138 LocalFree(inArgv); |
|
139 LocalFree(outArgv); |
|
140 free(inCmdLineNew); |
|
141 free(outCmdLineNew); |
|
142 free(outCmdLine); |
|
143 return rv; |
|
144 } |
|
145 |
|
146 if (rv == 0) { |
|
147 if (passes) { |
|
148 wprintf(L"TEST-PASS | %s | check %2d\n", TEST_NAME, testNum); |
|
149 } else { |
|
150 wprintf(L"TEST-UNEXPECTED-PASS | %s | check %2d\n", TEST_NAME, testNum); |
|
151 rv = 1; |
|
152 } |
|
153 } |
|
154 |
|
155 LocalFree(inArgv); |
|
156 LocalFree(outArgv); |
|
157 free(inCmdLineNew); |
|
158 free(outCmdLineNew); |
|
159 free(outCmdLine); |
|
160 return rv; |
|
161 } |
|
162 |
|
163 int wmain(int argc, wchar_t *argv[]) |
|
164 { |
|
165 int i; |
|
166 int rv = 0; |
|
167 |
|
168 if (argc > 1 && (_wcsicmp(argv[1], L"-check-one") != 0 || |
|
169 _wcsicmp(argv[1], L"-check-one") == 0 && argc != 3)) { |
|
170 fwprintf(stderr, L"Displays and validates output from MakeCommandLine.\n\n"); |
|
171 fwprintf(stderr, L"Usage: %s -check-one <test number>\n\n", argv[0]); |
|
172 fwprintf(stderr, L" <test number>\tSpecifies the test number to run from the\n"); |
|
173 fwprintf(stderr, L"\t\tTestXREMakeCommandLineWin.ini file.\n"); |
|
174 return 255; |
|
175 } |
|
176 |
|
177 wchar_t inifile[MAXPATHLEN]; |
|
178 if (!::GetModuleFileNameW(0, inifile, MAXPATHLEN)) { |
|
179 wprintf(L"TEST-UNEXPECTED-FAIL | %s | GetModuleFileNameW\n", TEST_NAME); |
|
180 return 2; |
|
181 } |
|
182 |
|
183 WCHAR *slash = wcsrchr(inifile, '\\'); |
|
184 if (!slash) { |
|
185 wprintf(L"TEST-UNEXPECTED-FAIL | %s | wcsrchr\n", TEST_NAME); |
|
186 return 3; |
|
187 } |
|
188 |
|
189 wcscpy(slash + 1, L"TestXREMakeCommandLineWin.ini\0"); |
|
190 |
|
191 for (i = 0; i < MAX_TESTS; ++i) { |
|
192 wchar_t sInputVal[MAXPATHLEN]; |
|
193 wchar_t sOutputVal[MAXPATHLEN]; |
|
194 wchar_t sPassesVal[MAXPATHLEN]; |
|
195 wchar_t sInputKey[MAXPATHLEN]; |
|
196 wchar_t sOutputKey[MAXPATHLEN]; |
|
197 wchar_t sPassesKey[MAXPATHLEN]; |
|
198 |
|
199 if (argc > 2 && _wcsicmp(argv[1], L"-check-one") == 0 && argc == 3) { |
|
200 i = _wtoi(argv[2]); |
|
201 } |
|
202 |
|
203 _snwprintf(sInputKey, MAXPATHLEN, L"input_%d", i); |
|
204 _snwprintf(sOutputKey, MAXPATHLEN, L"output_%d", i); |
|
205 _snwprintf(sPassesKey, MAXPATHLEN, L"passes_%d", i); |
|
206 |
|
207 if (!GetPrivateProfileStringW(L"MakeCommandLineTests", sInputKey, nullptr, |
|
208 sInputVal, MAXPATHLEN, inifile)) { |
|
209 if (i == 0 || argc > 2 && _wcsicmp(argv[1], L"-check-one") == 0) { |
|
210 wprintf(L"TEST-UNEXPECTED-FAIL | %s | see following explanation:\n", TEST_NAME); |
|
211 wprintf(L"ERROR: Either the TestXREMakeCommandLineWin.ini file doesn't exist\n"); |
|
212 if (argc > 1 && _wcsicmp(argv[1], L"-check-one") == 0 && argc == 3) { |
|
213 wprintf(L"ERROR: or the test is not defined in the MakeCommandLineTests section.\n"); |
|
214 } else { |
|
215 wprintf(L"ERROR: or it has no tests defined in the MakeCommandLineTests section.\n"); |
|
216 } |
|
217 wprintf(L"ERROR: File: %s\n", inifile); |
|
218 return 4; |
|
219 } |
|
220 break; |
|
221 } |
|
222 |
|
223 GetPrivateProfileStringW(L"MakeCommandLineTests", sOutputKey, nullptr, |
|
224 sOutputVal, MAXPATHLEN, inifile); |
|
225 GetPrivateProfileStringW(L"MakeCommandLineTests", sPassesKey, nullptr, |
|
226 sPassesVal, MAXPATHLEN, inifile); |
|
227 |
|
228 rv |= verifyCmdLineCreation(sInputVal, sOutputVal, |
|
229 (_wcsicmp(sPassesVal, L"false") == 0) ? FALSE : TRUE, |
|
230 i); |
|
231 |
|
232 if (argc > 2 && _wcsicmp(argv[1], L"-check-one") == 0) { |
|
233 break; |
|
234 } |
|
235 } |
|
236 |
|
237 if (rv == 0) { |
|
238 wprintf(L"TEST-PASS | %s | all checks passed\n", TEST_NAME); |
|
239 } else { |
|
240 wprintf(L"TEST-UNEXPECTED-FAIL | %s | some checks failed\n", TEST_NAME); |
|
241 } |
|
242 |
|
243 return rv; |
|
244 } |
|
245 |
|
246 #ifdef __MINGW32__ |
|
247 |
|
248 /* MingW currently does not implement a wide version of the |
|
249 startup routines. Workaround is to implement something like |
|
250 it ourselves. See bug 411826 */ |
|
251 |
|
252 #include <shellapi.h> |
|
253 |
|
254 int main(int argc, char **argv) |
|
255 { |
|
256 LPWSTR commandLine = GetCommandLineW(); |
|
257 int argcw = 0; |
|
258 LPWSTR *argvw = CommandLineToArgvW(commandLine, &argcw); |
|
259 if (!argvw) |
|
260 return 127; |
|
261 |
|
262 int result = wmain(argcw, argvw); |
|
263 LocalFree(argvw); |
|
264 return result; |
|
265 } |
|
266 #endif /* __MINGW32__ */ |