Add a simple test for the CreateProcess NewConsole standard handle case.

Simplify checkModernConsoleHandleInit usage; it isn't necessary to build
a list of potential console handles.  We can just scan for them.
This commit is contained in:
Ryan Prichard 2015-10-25 19:50:57 -05:00
parent 7ad3f28f48
commit 45a38be9e4
5 changed files with 74 additions and 12 deletions

View File

@ -0,0 +1,56 @@
#include <TestCommon.h>
//
// Test CreateProcess when called with these parameters:
// - STARTF_USESTDHANDLES is not specified
// - bInheritHandles=FALSE or bInheritHandles=TRUE
// - CreationConsoleMode=NewConsole
//
template <typename T>
static void extend(std::vector<T> &base, const std::vector<T> &to_add) {
base.insert(base.end(), to_add.begin(), to_add.end());
}
REGISTER(Test_CreateProcess_NewConsole, always);
static void Test_CreateProcess_NewConsole() {
auto check = [](Worker &p, bool inheritHandles) {
auto c = p.child({ inheritHandles, CREATE_NEW_CONSOLE });
if (isTraditionalConio()) {
checkInitConsoleHandleSet(c);
} else {
checkModernConsoleHandleInit(c, true, true, true);
}
return c;
};
{
Worker p;
check(p, true);
check(p, false);
}
{
Worker p;
p.openConin(false).setStdin();
p.newBuffer(false).setStdout().dup(true).setStderr();
check(p, true);
check(p, false);
}
if (isModernConio()) {
// The default Unbound console handles should be inheritable, so with
// bInheritHandles=TRUE, the child process should have six console
// handles, all usable.
Worker p;
auto c = check(p, true);
std::vector<uint64_t> expected;
extend(expected, handleInts(stdHandles(p)));
extend(expected, handleInts(stdHandles(c)));
std::sort(expected.begin(), expected.end());
auto correct = handleInts(c.scanForConsoleHandles());
std::sort(correct.begin(), correct.end());
CHECK(expected == correct);
}
}

View File

@ -147,9 +147,6 @@ static void Test_CreateProcess_UseStdHandles() {
}
}
} else {
auto nonReuseCheck = stdHandles(p);
nonReuseCheck.insert(nonReuseCheck.end(),
newHandles.begin(), newHandles.end());
ObjectSnap snap;
bool consoleOpened[3] = {false, false, false};
for (int i = 0; i < 3; ++i) {
@ -176,8 +173,7 @@ static void Test_CreateProcess_UseStdHandles() {
checkModernConsoleHandleInit(c,
consoleOpened[0],
consoleOpened[1],
consoleOpened[2],
nonReuseCheck);
consoleOpened[2]);
}
};

View File

@ -45,6 +45,7 @@ HANDLETESTS_OBJECTS = \
build/obj/HandleTests/CreateProcess_DefaultInherit.o \
build/obj/HandleTests/CreateProcess_DefaultInherit_PseudoHandleBug.o \
build/obj/HandleTests/CreateProcess_DefaultInherit_XPPipeBug.o \
build/obj/HandleTests/CreateProcess_NewConsole.o \
build/obj/HandleTests/CreateProcess_UseStdHandles.o \
build/obj/HandleTests/MiscTests.o \
build/obj/HandleTests/Modern.o \

View File

@ -225,16 +225,26 @@ bool isUnboundConsoleObject(RemoteHandle h) {
}
void checkModernConsoleHandleInit(RemoteWorker &proc,
bool in, bool out, bool err,
std::vector<RemoteHandle> nonReuseCheck) {
bool in, bool out, bool err) {
// List all the usable console handles that weren't just opened.
std::vector<RemoteHandle> preExistingHandles;
for (auto h : proc.scanForConsoleHandles()) {
if ((in && h.value() == proc.getStdin().value()) ||
(out && h.value() == proc.getStdout().value()) ||
(err && h.value() == proc.getStderr().value())) {
continue;
}
preExistingHandles.push_back(h);
}
ObjectSnap snap;
auto checkNonReuse = [&](RemoteHandle h) {
// The new Unbound console objects should not be inherited from
// anywhere else -- they should be brand new objects.
for (auto other : nonReuseCheck) {
// The Unbound console objects that were just opened should not be
// inherited from anywhere else -- they should be brand new objects.
for (auto other : preExistingHandles) {
CHECK(!snap.eq(h, other));
}
};
if (in) {
CHECK(isUsableConsoleInputHandle(proc.getStdin()));
CHECK(isUnboundConsoleObject(proc.getStdin()));

View File

@ -78,5 +78,4 @@ bool isUsableConsoleInputHandle(RemoteHandle h);
bool isUsableConsoleOutputHandle(RemoteHandle h);
bool isUnboundConsoleObject(RemoteHandle h);
void checkModernConsoleHandleInit(RemoteWorker &proc,
bool in, bool out, bool err,
std::vector<RemoteHandle> nonReuseCheck);
bool in, bool out, bool err);