Created
April 3, 2013 05:35
-
-
Save JesseKPhillips/5298688 to your computer and use it in GitHub Desktop.
Unittests pulled from std.process (DLang)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import std.process2; | |
import std.stdio, std.array; | |
void main(string[] args) { write(args.join("\0")); } | |
unittest | |
{ | |
import std.ascii; | |
auto x = executeShell("echo wyda"); | |
// @@@ This fails on wine | |
version(Posix) | |
assert(x.output == "wyda" ~ newline); | |
} | |
version (Posix) unittest | |
{ | |
environment["wyda"] = "geeba"; | |
assert(environment["wyda"] == "geeba"); | |
// Get again to make sure caching works | |
assert(environment["wyda"] == "geeba"); | |
environment.remove("wyda"); | |
assert(environment.get("wyda", "empty") == "empty"); | |
} | |
unittest | |
{ | |
// New variable | |
environment["std_process"] = "foo"; | |
assert (environment["std_process"] == "foo"); | |
// Set variable again | |
environment["std_process"] = "bar"; | |
assert (environment["std_process"] == "bar"); | |
// Remove variable | |
environment.remove("std_process"); | |
// Remove again, should succeed | |
environment.remove("std_process"); | |
// Throw on not found. | |
try { environment["std_process"]; assert(0); } catch(Exception e) { } | |
// get() without default value | |
assert (environment.get("std.process") == null); | |
// get() with default value | |
assert (environment.get("std_process", "baz") == "baz"); | |
// Convert to associative array | |
auto aa = environment.toAA(); | |
assert (aa.length > 0); | |
foreach (n, v; aa) | |
{ | |
// Wine has some bugs related to environment variables: | |
// - Wine allows the existence of an env. variable with the name | |
// "\0", but GetEnvironmentVariable refuses to retrieve it. | |
// - If an env. variable has zero length, i.e. is "\0", | |
// GetEnvironmentVariable should return 1. Instead it returns | |
// 0, indicating the variable doesn't exist. | |
version(Windows) if (n.length == 0 || v.length == 0) continue; | |
// why does this happen? | |
// n = "temp" || "tmp" | |
// v = "C:\Users\ADMINI~1\AppData\Local\Temp\2" | |
// e[n] = "C:\cygwin\tmp" | |
// for n = "TEMP" or "TMP", v and en[v] are both "C:\cygwin\tmp" | |
version(Windows) if (n == "temp" || n == "tmp") continue; | |
//printf("%.*s, %.*s, %.*s\n", n.length, n.ptr, v.length, v.ptr, environment[n].length, environment[n].ptr); | |
assert (v == environment[n]); | |
} | |
} | |
version(Windows) version(unittest) | |
{ | |
import core.sys.windows.windows; | |
import core.stdc.stddef; | |
extern (Windows) wchar_t** CommandLineToArgvW(wchar_t*, int*); | |
extern (C) size_t wcslen(in wchar *); | |
unittest | |
{ | |
string[] testStrings = [ | |
`Hello`, | |
`Hello, world`, | |
`Hello, "world"`, | |
`C:\`, | |
`C:\dmd`, | |
`C:\Program Files\`, | |
]; | |
enum CHARS = `_x\" *&^`; // _ is placeholder for nothing | |
foreach (c1; CHARS) | |
foreach (c2; CHARS) | |
foreach (c3; CHARS) | |
foreach (c4; CHARS) | |
testStrings ~= [c1, c2, c3, c4].replace("_", ""); | |
foreach (s; testStrings) | |
{ | |
auto q = escapeWindowsArgument(s); | |
LPWSTR lpCommandLine = (to!(wchar[])("Dummy.exe " ~ q) ~ "\0"w).ptr; | |
int numArgs; | |
LPWSTR* args = CommandLineToArgvW(lpCommandLine, &numArgs); | |
scope(exit) LocalFree(args); | |
assert(numArgs==2, s ~ " => " ~ q ~ " #" ~ text(numArgs-1)); | |
auto arg = to!string(args[1][0..wcslen(args[1])]); | |
assert(arg == s, s ~ " => " ~ q ~ " => " ~ arg); | |
} | |
} | |
} | |
version(unittest_burnin) | |
unittest | |
{ | |
// There are no readily-available commands on all platforms suitable | |
// for properly testing command escaping. The behavior of CMD's "echo" | |
// built-in differs from the POSIX program, and Windows ports of POSIX | |
// environments (Cygwin, msys, gnuwin32) may interfere with their own | |
// "echo" ports. | |
// To run this unit test, create std_process_unittest_helper.d with the | |
// following content and compile it: | |
// import std.stdio, std.array; void main(string[] args) { write(args.join("\0")); } | |
// Then, test this module with: | |
// rdmd --main -unittest -version=unittest_burnin process.d | |
import std.path; | |
import std.string; | |
import std.random; | |
import std.file; | |
auto helper = absolutePath("std_process_unittest_helper"); | |
assert(executeShell(helper ~ " hello").output.split("\0")[1..$] == ["hello"], "Helper malfunction"); | |
void test(string[] s, string fn) | |
{ | |
string e; | |
string[] g; | |
e = escapeShellCommand(helper ~ s); | |
{ | |
scope(failure) writefln("shell() failed.\nExpected:\t%s\nEncoded:\t%s", s, [e]); | |
g = executeShell(e).output.split("\0")[1..$]; | |
} | |
assert(s == g, format("shell() test failed.\nExpected:\t%s\nGot:\t\t%s\nEncoded:\t%s", s, g, [e])); | |
e = escapeShellCommand(helper ~ s) ~ ">" ~ escapeShellFileName(fn); | |
{ | |
scope(failure) writefln("system() failed.\nExpected:\t%s\nFilename:\t%s\nEncoded:\t%s", s, [fn], [e]); | |
executeShell(e); | |
g = readText(fn).split("\0")[1..$]; | |
} | |
remove(fn); | |
assert(s == g, format("system() test failed.\nExpected:\t%s\nGot:\t\t%s\nEncoded:\t%s", s, g, [e])); | |
} | |
while (true) | |
{ | |
string[] args; | |
foreach (n; 0..uniform(1, 4)) | |
{ | |
string arg; | |
foreach (l; 0..uniform(0, 10)) | |
{ | |
dchar c; | |
while (true) | |
{ | |
version (Windows) | |
{ | |
// As long as DMD's system() uses CreateProcessA, | |
// we can't reliably pass Unicode | |
c = uniform(0, 128); | |
} | |
else | |
c = uniform!ubyte(); | |
if (c == 0) | |
continue; // argv-strings are zero-terminated | |
version (Windows) | |
if (c == '\r' || c == '\n') | |
continue; // newlines are unescapable on Windows | |
break; | |
} | |
arg ~= c; | |
} | |
args ~= arg; | |
} | |
// generate filename | |
string fn = "test_"; | |
foreach (l; 0..uniform(1, 10)) | |
{ | |
dchar c; | |
while (true) | |
{ | |
version (Windows) | |
c = uniform(0, 128); // as above | |
else | |
c = uniform!ubyte(); | |
if (c == 0 || c == '/') | |
continue; // NUL and / are the only characters | |
// forbidden in POSIX filenames | |
version (Windows) | |
if (c < '\x20' || c == '<' || c == '>' || c == ':' || | |
c == '"' || c == '\\' || c == '|' || c == '?' || c == '*') | |
continue; // http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx | |
break; | |
} | |
fn ~= c; | |
} | |
test(args, fn); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment