diff options
Diffstat (limited to '')
-rw-r--r-- | toolkit/xre/test/win/TestXREMakeCommandLineWin.cpp | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/toolkit/xre/test/win/TestXREMakeCommandLineWin.cpp b/toolkit/xre/test/win/TestXREMakeCommandLineWin.cpp new file mode 100644 index 0000000000..c12550c3d6 --- /dev/null +++ b/toolkit/xre/test/win/TestXREMakeCommandLineWin.cpp @@ -0,0 +1,266 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include <stdio.h> +#include <stdlib.h> +#include <windows.h> +// Support for _setmode +#include <fcntl.h> +#include <io.h> + +#include "nsWindowsRestart.cpp" + +// CommandLineToArgvW may return different values for argv[0] since it contains +// the path to the binary that was executed so we prepend an argument that is +// quoted with a space to prevent argv[1] being appended to argv[0]. +#define DUMMY_ARG1 L"\"arg 1\" " + +#ifndef MAXPATHLEN +# ifdef PATH_MAX +# define MAXPATHLEN PATH_MAX +# elif defined(MAX_PATH) +# define MAXPATHLEN MAX_PATH +# elif defined(_MAX_PATH) +# define MAXPATHLEN _MAX_PATH +# elif defined(CCHMAXPATH) +# define MAXPATHLEN CCHMAXPATH +# else +# define MAXPATHLEN 1024 +# endif +#endif + +#define TEST_NAME L"XRE MakeCommandLine" +#define MAX_TESTS 100 + +// Verbose output can be enabled by defining VERBOSE 1 +#define VERBOSE 0 + +// Compares compareCmdLine with the output of MakeCommandLine. This is +// accomplished by converting inCmdLine to an argument list with +// CommandLineToArgvW and converting it back to a command line with +// MakeCommandLine. +static int verifyCmdLineCreation(wchar_t* inCmdLine, wchar_t* compareCmdLine, + bool passes, int testNum) { + int rv = 0; + int i; + int inArgc; + int outArgc; + bool isEqual; + + // When debugging with command lines containing Unicode characters greater + // than 255 you can set the mode for stdout to Unicode so the console will + // receive the correct characters though it won't display them properly unless + // the console's font has been set to one that can display the characters. You + // can also redirect the console output to a file that has been saved as + // Unicode to view the characters. + // _setmode(_fileno(stdout), _O_WTEXT); + + // Prepend an additional argument to the command line. CommandLineToArgvW + // handles argv[0] differently than other arguments since argv[0] is the path + // to the binary being executed and MakeCommandLine only handles argv[1] and + // larger. + wchar_t* inCmdLineNew = (wchar_t*)malloc( + (wcslen(DUMMY_ARG1) + wcslen(inCmdLine) + 1) * sizeof(wchar_t)); + wcscpy(inCmdLineNew, DUMMY_ARG1); + wcscat(inCmdLineNew, inCmdLine); + LPWSTR* inArgv = CommandLineToArgvW(inCmdLineNew, &inArgc); + + auto outCmdLine = mozilla::MakeCommandLine(inArgc - 1, inArgv + 1); + wchar_t* outCmdLineNew = (wchar_t*)malloc( + (wcslen(DUMMY_ARG1) + wcslen(outCmdLine.get()) + 1) * sizeof(wchar_t)); + wcscpy(outCmdLineNew, DUMMY_ARG1); + wcscat(outCmdLineNew, outCmdLine.get()); + LPWSTR* outArgv = CommandLineToArgvW(outCmdLineNew, &outArgc); + + if (VERBOSE) { + wprintf(L"\n"); + wprintf(L"Verbose Output\n"); + wprintf(L"--------------\n"); + wprintf(L"Input command line : >%s<\n", inCmdLine); + wprintf(L"MakeComandLine output: >%s<\n", outCmdLine.get()); + wprintf(L"Expected command line: >%s<\n", compareCmdLine); + + wprintf(L"input argc : %d\n", inArgc - 1); + wprintf(L"output argc: %d\n", outArgc - 1); + + for (i = 1; i < inArgc; ++i) { + wprintf(L"input argv[%d] : >%s<\n", i - 1, inArgv[i]); + } + + for (i = 1; i < outArgc; ++i) { + wprintf(L"output argv[%d]: >%s<\n", i - 1, outArgv[i]); + } + wprintf(L"\n"); + } + + isEqual = (inArgc == outArgc); + if (!isEqual) { + wprintf(L"TEST-%s-FAIL | %s | ARGC Comparison (check %2d)\n", + passes ? L"UNEXPECTED" : L"KNOWN", TEST_NAME, testNum); + if (passes) { + rv = 1; + } + LocalFree(inArgv); + LocalFree(outArgv); + free(inCmdLineNew); + free(outCmdLineNew); + return rv; + } + + for (i = 1; i < inArgc; ++i) { + isEqual = (wcscmp(inArgv[i], outArgv[i]) == 0); + if (!isEqual) { + wprintf(L"TEST-%s-FAIL | %s | ARGV Comparison (check %2d)\n", + passes ? L"UNEXPECTED" : L"KNOWN", TEST_NAME, testNum); + if (passes) { + rv = 1; + } + LocalFree(inArgv); + LocalFree(outArgv); + free(inCmdLineNew); + free(outCmdLineNew); + return rv; + } + } + + isEqual = (wcscmp(outCmdLine.get(), compareCmdLine) == 0); + if (!isEqual) { + wprintf(L"TEST-%s-FAIL | %s | Command Line Comparison (check %2d)\n", + passes ? L"UNEXPECTED" : L"KNOWN", TEST_NAME, testNum); + if (passes) { + rv = 1; + } + LocalFree(inArgv); + LocalFree(outArgv); + free(inCmdLineNew); + free(outCmdLineNew); + return rv; + } + + if (rv == 0) { + if (passes) { + wprintf(L"TEST-PASS | %s | check %2d\n", TEST_NAME, testNum); + } else { + wprintf(L"TEST-UNEXPECTED-PASS | %s | check %2d\n", TEST_NAME, testNum); + rv = 1; + } + } + + LocalFree(inArgv); + LocalFree(outArgv); + free(inCmdLineNew); + free(outCmdLineNew); + return rv; +} + +int wmain(int argc, wchar_t* argv[]) { + int i; + int rv = 0; + + if (argc > 1 && (_wcsicmp(argv[1], L"-check-one") != 0 || argc != 3)) { + fwprintf(stderr, + L"Displays and validates output from MakeCommandLine.\n\n"); + fwprintf(stderr, L"Usage: %s -check-one <test number>\n\n", argv[0]); + fwprintf(stderr, + L" <test number>\tSpecifies the test number to run from the\n"); + fwprintf(stderr, L"\t\tTestXREMakeCommandLineWin.ini file.\n"); + return 255; + } + + wchar_t inifile[MAXPATHLEN]; + if (!::GetModuleFileNameW(0, inifile, MAXPATHLEN)) { + wprintf(L"TEST-UNEXPECTED-FAIL | %s | GetModuleFileNameW\n", TEST_NAME); + return 2; + } + + WCHAR* slash = wcsrchr(inifile, '\\'); + if (!slash) { + wprintf(L"TEST-UNEXPECTED-FAIL | %s | wcsrchr\n", TEST_NAME); + return 3; + } + + wcscpy(slash + 1, L"TestXREMakeCommandLineWin.ini\0"); + + for (i = 0; i < MAX_TESTS; ++i) { + wchar_t sInputVal[MAXPATHLEN]; + wchar_t sOutputVal[MAXPATHLEN]; + wchar_t sPassesVal[MAXPATHLEN]; + wchar_t sInputKey[MAXPATHLEN]; + wchar_t sOutputKey[MAXPATHLEN]; + wchar_t sPassesKey[MAXPATHLEN]; + + if (argc > 2 && _wcsicmp(argv[1], L"-check-one") == 0 && argc == 3) { + i = _wtoi(argv[2]); + } + + _snwprintf(sInputKey, MAXPATHLEN, L"input_%d", i); + _snwprintf(sOutputKey, MAXPATHLEN, L"output_%d", i); + _snwprintf(sPassesKey, MAXPATHLEN, L"passes_%d", i); + + if (!GetPrivateProfileStringW(L"MakeCommandLineTests", sInputKey, nullptr, + sInputVal, MAXPATHLEN, inifile)) { + if (i == 0 || (argc > 2 && _wcsicmp(argv[1], L"-check-one") == 0)) { + wprintf(L"TEST-UNEXPECTED-FAIL | %s | see following explanation:\n", + TEST_NAME); + wprintf( + L"ERROR: Either the TestXREMakeCommandLineWin.ini file doesn't " + L"exist\n"); + if (argc > 1 && _wcsicmp(argv[1], L"-check-one") == 0 && argc == 3) { + wprintf( + L"ERROR: or the test is not defined in the MakeCommandLineTests " + L"section.\n"); + } else { + wprintf( + L"ERROR: or it has no tests defined in the MakeCommandLineTests " + L"section.\n"); + } + wprintf(L"ERROR: File: %s\n", inifile); + return 4; + } + break; + } + + GetPrivateProfileStringW(L"MakeCommandLineTests", sOutputKey, nullptr, + sOutputVal, MAXPATHLEN, inifile); + GetPrivateProfileStringW(L"MakeCommandLineTests", sPassesKey, nullptr, + sPassesVal, MAXPATHLEN, inifile); + + rv |= verifyCmdLineCreation( + sInputVal, sOutputVal, + (_wcsicmp(sPassesVal, L"false") == 0) ? FALSE : TRUE, i); + + if (argc > 2 && _wcsicmp(argv[1], L"-check-one") == 0) { + break; + } + } + + if (rv == 0) { + wprintf(L"TEST-PASS | %s | all checks passed\n", TEST_NAME); + } else { + wprintf(L"TEST-UNEXPECTED-FAIL | %s | some checks failed\n", TEST_NAME); + } + + return rv; +} + +#ifdef __MINGW32__ + +/* MingW currently does not implement a wide version of the + startup routines. Workaround is to implement something like + it ourselves. See bug 411826 */ + +# include <shellapi.h> + +int main(int argc, char** argv) { + LPWSTR commandLine = GetCommandLineW(); + int argcw = 0; + LPWSTR* argvw = CommandLineToArgvW(commandLine, &argcw); + if (!argvw) return 127; + + int result = wmain(argcw, argvw); + LocalFree(argvw); + return result; +} +#endif /* __MINGW32__ */ |