Browse Source

Update test to test closeStdin() with multiple Child instances,

and to run under valgrind.

Note:  Valgrind reports 72,704 bytes reachable in testChild and childProgram.
This might not indicate any problem.


git-svn-id: https://svn.microneil.com/svn/CodeDweller-Tests/trunk@59 b3372362-9eaa-4a85-aa2b-6faa1ab7c995
master
adeniz 8 years ago
parent
commit
26f56e3de2
2 changed files with 178 additions and 23 deletions
  1. 22
    1
      TestChild/childProgram.cpp
  2. 156
    22
      TestChild/testChild.cpp

+ 22
- 1
TestChild/childProgram.cpp View File

@@ -1,5 +1,7 @@
#include <iostream>
#ifdef DEBUG_MESSAGES
#include <fstream> // debug
#endif
#include <string>
#include <thread>
#include <chrono>
@@ -7,7 +9,9 @@
int
main(int argc, char *argv[]) {
#ifdef DEBUG_MESSAGES
std::ofstream log("childProgram.log");
#endif
int returnStatus = 25; // Successful return.
@@ -16,8 +20,10 @@ main(int argc, char *argv[]) {
// Write a single line and exit.
if (std::string(argv[1]) == "write") {
#ifdef DEBUG_MESSAGES
log << "Command is \"write\". Returning \"This is a test\""
<< " to stdout and stderr." << std::endl;
#endif
std::cout << "This ";
std::cout.flush();
@@ -36,8 +42,9 @@ main(int argc, char *argv[]) {
// Exit without writing anything.
if (std::string(argv[1]) == "quit") {
#ifdef DEBUG_MESSAGES
log << "Command is \"quit\". Exiting" << std::endl;
#endif
goto exit;
}
@@ -45,18 +52,24 @@ main(int argc, char *argv[]) {
// Wait for standard input to close, and exit.
if (std::string(argv[1]) == "checkStdinEOF") {
#ifdef DEBUG_MESSAGES
log << "Command is \"checkStdinEOF\". Checking that stdin is closed."
<< std::endl;
#endif
std::string temp;
std::cin >> temp;
if (std::cin.eof()) {
#ifdef DEBUG_MESSAGES
log << "stdin was closed." << std::endl;
#endif
returnStatus = 15; // Successful return.
} else {
#ifdef DEBUG_MESSAGES
log << "stdin was not closed." << std::endl;
#endif
returnStatus = 10; // Unsuccessful return.
}
@@ -67,25 +80,33 @@ main(int argc, char *argv[]) {
}
char ch;
#ifdef DEBUG_MESSAGES
log << "Received \"";
#endif
while (std::cin >> ch) {
// Exit?
if ('q' == ch) {
#ifdef DEBUG_MESSAGES
log << (char) ch << "\"" << std::endl;
#endif
break;
}
std::cout << (char) std::toupper(ch);
std::cout.flush();
#ifdef DEBUG_MESSAGES
log << (char) ch;
log.flush();
#endif
}
exit:
#ifdef DEBUG_MESSAGES
log.close();
#endif
std::this_thread::sleep_for(std::chrono::milliseconds(50));
return returnStatus;

+ 156
- 22
TestChild/testChild.cpp View File

@@ -197,7 +197,7 @@ bool doReadWrite(size_t bufSize,
}
// Verify exit.
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
if (!child.isDone()) {
std::cout << " Failure in testChildNonblockingReadWrite2: "
@@ -257,7 +257,7 @@ bool testChildStreamIsDone() {
child.flush();
// Sleep to let the child exit.
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
if (!child.isDone()) {
std::cout << "isDone() failure; returned false." << std::endl;
@@ -884,7 +884,7 @@ bool testChildIsDone() {
}
// Sleep to let the child exit.
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
if (!child.isDone()) {
std::cout << "isDone() failure; returned false." << std::endl;
@@ -928,7 +928,7 @@ bool testChildIsRunning() {
}
// Sleep to let the child exit.
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
child.close();
@@ -974,7 +974,7 @@ bool testChildResult() {
}
// Wait for the child to exit.
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
int32_t result = child.result();
@@ -1016,7 +1016,7 @@ bool testChildClose() {
try {
CodeDweller::Child child(childName);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
child.close();
} catch (std::exception &e) {
EXCEPTION_TERM("close() with 100 ms waiting");
@@ -1036,7 +1036,7 @@ bool testChildClose() {
RETURN_FALSE(" write() failure");
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
child.close();
@@ -1099,7 +1099,7 @@ bool testChildStdInClose() {
child.closeStdIn();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
int32_t result = child.result();
@@ -1135,7 +1135,7 @@ bool testChildStdInClose() {
RETURN_FALSE(" write() failure");
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
child.closeStdIn();
@@ -1159,6 +1159,131 @@ bool testChildStdInClose() {
}
bool testChildrenStdInClose() {
std::string errorDescription;
int const nChildren = 5;
// Test with no child process.
try {
CodeDweller::Child child;
child.closeStdIn();
NO_EXCEPTION_TERM("closeStdIn() with no child process");
return false;
} catch (std::exception &e) {
}
// Test with no waiting.
try {
CodeDweller::Child child[nChildren];
for (int i = 0; i < nChildren; i++) {
child[i].open(childName);
}
for (int i = 0; i < nChildren; i++) {
child[i].closeStdIn();
}
for (int i = 0; i < nChildren; i++) {
child[i].close();
}
} catch (std::exception &e) {
EXCEPTION_TERM("closeStdIn() with no waiting");
return false;
}
// Run child that waits for stdin to close.
std::vector<std::string> cmd;
cmd.push_back(childName);
cmd.push_back("checkStdinEOF");
try {
CodeDweller::Child child[nChildren];
for (int i = 0; i < nChildren; i++ ) {
child[i].open(cmd);
}
for (int i = 0; i < nChildren; i++) {
child[i].closeStdIn();
}
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
for (int i = 0; i < nChildren; i++) {
int32_t result = child[i].result();
if (15 != result) {
std::cout << "closeStdIn() failure for child " << i << "; returned "
<< result << " instead of 15." << std::endl;
return false;
}
}
for (int i = 0; i < nChildren; i++) {
child[i].close();
}
for (int i = 0; i < nChildren; i++) {
if (child[i].errorOccurred(errorDescription)) {
std::ostringstream temp;
temp << " Failure in: testChildStdInClose for child " << i
<< ": " << errorDescription;
RETURN_FALSE(temp.str());
}
}
} catch (std::exception &e) {
EXCEPTION_TERM("closeStdIn() or close()");
return false;
}
// Test after the child exits.
cmd.clear();
cmd.push_back(childName);
cmd.push_back("quit");
try {
CodeDweller::Child child[nChildren];
for (int i = 0; i < nChildren; i++) {
child[i].open(cmd);
}
for (int i = 0; i < nChildren; i++) {
if (!child[i].write("q")) {
RETURN_FALSE(" write() failure");
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
for (int i = 0; i < nChildren; i++) {
child[i].closeStdIn();
}
} catch (std::exception &e) {
EXCEPTION_TERM("closeStdIn() after child exits");
return false;
}
return true;
}
bool testChildOpen() {
// Test with no waiting.
@@ -1175,10 +1300,10 @@ bool testChildOpen() {
// Test with waiting.
try {
CodeDweller::Child child(childName);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
child.close();
child.open(childName);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
child.close();
} catch (std::exception &e) {
EXCEPTION_TERM("close()/open() with 100 ms waiting");
@@ -1304,6 +1429,8 @@ bool testChildReadWrite() {
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
if (0 != nCharToRead) {
@@ -1341,7 +1468,7 @@ bool testChildReadWrite() {
}
// Verify exit.
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
if (!child.isDone()) {
std::cout << " Failure in testReadWrite: Child program did not exit."
@@ -1417,7 +1544,7 @@ bool testChildIsFinishedWriting() {
}
// Verify exit.
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
if (!child.isDone()) {
std::cout << " Failure in testIsFinishedWriting: "
@@ -1481,7 +1608,7 @@ bool testChildRead() {
RETURN_FALSE(temp.str());
}
std::this_thread::sleep_for(std::chrono::milliseconds(10));
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
@@ -1495,7 +1622,13 @@ bool testChildRead() {
}
// Sleep to let the child exit.
std::this_thread::sleep_for(std::chrono::milliseconds(100));
for (int i = 0; i < 100; i++) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
if (child.isDone())
break;
}
if (!child.isDone()) {
std::cout << "first isDone() failure in testReader." << std::endl;
@@ -1541,7 +1674,7 @@ bool testChildNonBlockingReadWrite1() {
RETURN_FALSE(" first write() failure");
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
// Read one character.
std::string readBuf;
@@ -1609,7 +1742,7 @@ bool testChildNonBlockingReadWrite1() {
}
// Wait for reader thread to fill input buffer.
std::this_thread::sleep_for(std::chrono::milliseconds(25));
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
if (child.read(readBuf) != expectedLeftOver) {
RETURN_FALSE(" read() failure");
@@ -1625,7 +1758,7 @@ bool testChildNonBlockingReadWrite1() {
}
// Verify exit.
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
if (!child.isDone()) {
std::cout << " Failure in testChildNonblockingReadWrite1: "
@@ -1718,7 +1851,7 @@ bool testChildVectorReadWrite() {
RETURN_FALSE(" write() failure");
}
std::this_thread::sleep_for(std::chrono::milliseconds(50));
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
// Read one character.
std::vector<char> readBuf;
@@ -1816,7 +1949,7 @@ bool testChildVectorReadWrite() {
}
// Verify exit.
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
if (!child.isDone()) {
std::cout << " Failure in testChildVectorReadWrite: "
@@ -1868,7 +2001,7 @@ bool testChildReadDelimited() {
RETURN_FALSE(" write() failure");
}
std::this_thread::sleep_for(std::chrono::milliseconds(50));
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
// Check
std::vector<char> readVec;
@@ -1984,7 +2117,7 @@ bool testChildReadDelimited() {
}
// Verify exit.
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
if (!child.isDone()) {
std::cout << " Failure in testChildReadDelimited: "
@@ -2040,6 +2173,7 @@ int main()
RUN_TEST(testChildResult);
RUN_TEST(testChildClose);
RUN_TEST(testChildStdInClose);
RUN_TEST(testChildrenStdInClose);
RUN_TEST(testChildOpen);
RUN_TEST(testChildIsFinishedWriting);
RUN_TEST(testChildRead);

Loading…
Cancel
Save