toolkit/xre/test/win/TestXREMakeCommandLineWin.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial