|
|
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
// Command the child to exit.
|
|
|
// Command the child to exit.
|
|
|
child.writer << 'q';
|
|
|
|
|
|
child.writer.flush();
|
|
|
|
|
|
|
|
|
child.childStream << 'q';
|
|
|
|
|
|
child.childStream.flush();
|
|
|
|
|
|
|
|
|
// Sleep to let the child exit.
|
|
|
// Sleep to let the child exit.
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Test exception.
|
|
|
// Test exception.
|
|
|
try {
|
|
|
try {
|
|
|
child.writer.exceptions(std::ostream::failbit | std::ostream::badbit);
|
|
|
|
|
|
child.writer << bufSize;
|
|
|
|
|
|
child.writer.flush();
|
|
|
|
|
|
|
|
|
child.childStream.exceptions(std::ostream::failbit | std::ostream::badbit);
|
|
|
|
|
|
child.childStream << bufSize;
|
|
|
|
|
|
child.childStream.flush();
|
|
|
NO_EXCEPTION_TERM(" writer called without run()");
|
|
|
NO_EXCEPTION_TERM(" writer called without run()");
|
|
|
return false;
|
|
|
return false;
|
|
|
} catch (std::exception &e) {
|
|
|
} catch (std::exception &e) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Clear the writer stream.
|
|
|
// Clear the writer stream.
|
|
|
try {
|
|
|
try {
|
|
|
child.writer.clear();
|
|
|
|
|
|
|
|
|
child.childStream.clear();
|
|
|
} catch (std::exception &e) {
|
|
|
} catch (std::exception &e) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ptr = line.data();
|
|
|
ptr = line.data();
|
|
|
for (std::string::size_type i = 0; i < line.length(); i++) {
|
|
|
for (std::string::size_type i = 0; i < line.length(); i++) {
|
|
|
child.writer << ptr[i];
|
|
|
|
|
|
if (!child.writer) {
|
|
|
|
|
|
|
|
|
child.childStream << ptr[i];
|
|
|
|
|
|
if (!child.childStream) {
|
|
|
RETURN_FALSE(" Failure in testReaderWriter: writer stream is bad");
|
|
|
RETURN_FALSE(" Failure in testReaderWriter: writer stream is bad");
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
child.writer.flush();
|
|
|
|
|
|
if (!child.writer) {
|
|
|
|
|
|
|
|
|
child.childStream.flush();
|
|
|
|
|
|
if (!child.childStream) {
|
|
|
RETURN_FALSE(" Failure in testReaderWriter: writer stream is bad");
|
|
|
RETURN_FALSE(" Failure in testReaderWriter: writer stream is bad");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
readLine.erase();
|
|
|
readLine.erase();
|
|
|
for (std::string::size_type i = 0; i < line.length(); i++) {
|
|
|
for (std::string::size_type i = 0; i < line.length(); i++) {
|
|
|
child.reader >> readChar;
|
|
|
|
|
|
if (!child.reader) {
|
|
|
|
|
|
|
|
|
child.childStream >> readChar;
|
|
|
|
|
|
if (!child.childStream) {
|
|
|
RETURN_FALSE(" Failure in testReaderWriter: reader stream is bad");
|
|
|
RETURN_FALSE(" Failure in testReaderWriter: reader stream is bad");
|
|
|
}
|
|
|
}
|
|
|
readLine.push_back(readChar);
|
|
|
readLine.push_back(readChar);
|
|
|
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
// Send exit message.
|
|
|
// Send exit message.
|
|
|
child.writer << 'q';
|
|
|
|
|
|
child.writer.flush();
|
|
|
|
|
|
if (!child.writer) {
|
|
|
|
|
|
|
|
|
child.childStream << 'q';
|
|
|
|
|
|
child.childStream.flush();
|
|
|
|
|
|
if (!child.childStream) {
|
|
|
RETURN_FALSE(" Failure in testReaderWriter: writer stream is bad");
|
|
|
RETURN_FALSE(" Failure in testReaderWriter: writer stream is bad");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Test exception.
|
|
|
// Test exception.
|
|
|
try {
|
|
|
try {
|
|
|
int temp;
|
|
|
int temp;
|
|
|
child.reader.exceptions(std::istream::failbit | std::istream::badbit);
|
|
|
|
|
|
child.reader >> temp;
|
|
|
|
|
|
|
|
|
child.childStream.exceptions(std::istream::failbit | std::istream::badbit);
|
|
|
|
|
|
child.childStream >> temp;
|
|
|
NO_EXCEPTION_TERM(" reader called without run()");
|
|
|
NO_EXCEPTION_TERM(" reader called without run()");
|
|
|
return false;
|
|
|
return false;
|
|
|
} catch (std::exception &e) {
|
|
|
} catch (std::exception &e) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
child.reader.clear();
|
|
|
|
|
|
child.writer.clear();
|
|
|
|
|
|
|
|
|
child.childStream.clear();
|
|
|
|
|
|
child.childStream.clear();
|
|
|
std::ostringstream childOutput;
|
|
|
std::ostringstream childOutput;
|
|
|
std::string expectedChildOutput("This is a test");
|
|
|
std::string expectedChildOutput("This is a test");
|
|
|
char readChar;
|
|
|
char readChar;
|
|
|
|
|
|
|
|
|
child.run();
|
|
|
child.run();
|
|
|
child.reader.exceptions(std::istream::badbit);
|
|
|
|
|
|
child.reader >> std::noskipws;
|
|
|
|
|
|
if (!child.reader) {
|
|
|
|
|
|
|
|
|
child.childStream.exceptions(std::istream::badbit);
|
|
|
|
|
|
child.childStream >> std::noskipws;
|
|
|
|
|
|
if (!child.childStream) {
|
|
|
RETURN_FALSE(" Failure in testReader: reader stream is bad");
|
|
|
RETURN_FALSE(" Failure in testReader: reader stream is bad");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
while (child.reader >> readChar) {
|
|
|
|
|
|
|
|
|
while (child.childStream >> readChar) {
|
|
|
|
|
|
|
|
|
if (!child.reader) {
|
|
|
|
|
|
|
|
|
if (!child.childStream) {
|
|
|
RETURN_FALSE(" Failure in testReader: reader stream is bad");
|
|
|
RETURN_FALSE(" Failure in testReader: reader stream is bad");
|
|
|
}
|
|
|
}
|
|
|
child.reader.putback(readChar);
|
|
|
|
|
|
if (!child.reader) {
|
|
|
|
|
|
|
|
|
child.childStream.putback(readChar);
|
|
|
|
|
|
if (!child.childStream) {
|
|
|
RETURN_FALSE(" Failure in testReader: reader stream is bad");
|
|
|
RETURN_FALSE(" Failure in testReader: reader stream is bad");
|
|
|
}
|
|
|
}
|
|
|
child.reader >> readChar;
|
|
|
|
|
|
if (!child.reader) {
|
|
|
|
|
|
|
|
|
child.childStream >> readChar;
|
|
|
|
|
|
if (!child.childStream) {
|
|
|
RETURN_FALSE(" Failure in testReader: reader stream is bad");
|
|
|
RETURN_FALSE(" Failure in testReader: reader stream is bad");
|
|
|
}
|
|
|
}
|
|
|
childOutput << readChar;
|
|
|
childOutput << readChar;
|
|
|
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
if (!child.reader.eof()) {
|
|
|
|
|
|
|
|
|
if (!child.childStream.eof()) {
|
|
|
RETURN_FALSE(" Failure in testReader: Error occured before "
|
|
|
RETURN_FALSE(" Failure in testReader: Error occured before "
|
|
|
"EOF was reached while reading");
|
|
|
"EOF was reached while reading");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
// Write.
|
|
|
// Write.
|
|
|
std::string childInput("abc");
|
|
|
std::string childInput("abc");
|
|
|
|
|
|
|
|
|
child.writer << childInput;
|
|
|
|
|
|
child.writer.flush();
|
|
|
|
|
|
|
|
|
child.childStream << childInput;
|
|
|
|
|
|
child.childStream.flush();
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
|
|
|
|
|
|
|
|
// Read one character.
|
|
|
// Read one character.
|
|
|
char ch;
|
|
|
char ch;
|
|
|
|
|
|
|
|
|
child.reader.read(&ch, 1);
|
|
|
|
|
|
|
|
|
child.childStream.read(&ch, 1);
|
|
|
|
|
|
|
|
|
if (ch != 'A') {
|
|
|
if (ch != 'A') {
|
|
|
RETURN_FALSE(" reader.read() returned incorrect value");
|
|
|
RETURN_FALSE(" reader.read() returned incorrect value");
|
|
|
|
|
|
|
|
|
// Read.
|
|
|
// Read.
|
|
|
char buf[bufSize * 2];
|
|
|
char buf[bufSize * 2];
|
|
|
|
|
|
|
|
|
child.reader.read(buf, 2);
|
|
|
|
|
|
|
|
|
child.childStream.read(buf, 2);
|
|
|
buf[2] = '\0';
|
|
|
buf[2] = '\0';
|
|
|
|
|
|
|
|
|
std::string input(buf);
|
|
|
std::string input(buf);
|
|
|
|
|
|
|
|
|
expectedInput[i] = std::toupper(output[i]);
|
|
|
expectedInput[i] = std::toupper(output[i]);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
child.writer << output;
|
|
|
|
|
|
child.writer.flush();
|
|
|
|
|
|
|
|
|
child.childStream << output;
|
|
|
|
|
|
child.childStream.flush();
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
|
|
|
|
|
|
|
|
child.reader.read(&ch, 1);
|
|
|
|
|
|
|
|
|
child.childStream.read(&ch, 1);
|
|
|
|
|
|
|
|
|
int index = 0;
|
|
|
int index = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
size_t nBytesRead = expectedInput.size() - 1;
|
|
|
size_t nBytesRead = expectedInput.size() - 1;
|
|
|
|
|
|
|
|
|
child.reader.read(buf, nBytesRead);
|
|
|
|
|
|
|
|
|
child.childStream.read(buf, nBytesRead);
|
|
|
buf[nBytesRead] = '\0';
|
|
|
buf[nBytesRead] = '\0';
|
|
|
|
|
|
|
|
|
if (expectedInput.substr(index, nBytesRead) != std::string(buf)) {
|
|
|
if (expectedInput.substr(index, nBytesRead) != std::string(buf)) {
|
|
|
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
// Send exit message.
|
|
|
// Send exit message.
|
|
|
child.writer << 'q';
|
|
|
|
|
|
child.writer.flush();
|
|
|
|
|
|
if (!child.writer) {
|
|
|
|
|
|
|
|
|
child.childStream << 'q';
|
|
|
|
|
|
child.childStream.flush();
|
|
|
|
|
|
if (!child.childStream) {
|
|
|
RETURN_FALSE(" Failure in testNonblockingReader: writer stream is bad");
|
|
|
RETURN_FALSE(" Failure in testNonblockingReader: writer stream is bad");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Check for available input with input.
|
|
|
// Check for available input with input.
|
|
|
std::string childInput("abc");
|
|
|
std::string childInput("abc");
|
|
|
|
|
|
|
|
|
child.writer << childInput;
|
|
|
|
|
|
child.writer.flush();
|
|
|
|
|
|
|
|
|
child.childStream << childInput;
|
|
|
|
|
|
child.childStream.flush();
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
|
|
|
|
|
|
|
|
// Check that input is available.
|
|
|
// Check that input is available.
|
|
|
|
|
|
|
|
|
// Read one character.
|
|
|
// Read one character.
|
|
|
char ch;
|
|
|
char ch;
|
|
|
|
|
|
|
|
|
child.reader.read(&ch, 1);
|
|
|
|
|
|
|
|
|
child.childStream.read(&ch, 1);
|
|
|
|
|
|
|
|
|
if (ch != 'A') {
|
|
|
if (ch != 'A') {
|
|
|
RETURN_FALSE(" reader.read() returned incorrect value");
|
|
|
RETURN_FALSE(" reader.read() returned incorrect value");
|
|
|
|
|
|
|
|
|
// Read.
|
|
|
// Read.
|
|
|
char buf[bufSize * 2];
|
|
|
char buf[bufSize * 2];
|
|
|
|
|
|
|
|
|
child.reader.read(buf, 2);
|
|
|
|
|
|
|
|
|
child.childStream.read(buf, 2);
|
|
|
buf[2] = '\0';
|
|
|
buf[2] = '\0';
|
|
|
|
|
|
|
|
|
std::string input(buf);
|
|
|
std::string input(buf);
|
|
|
|
|
|
|
|
|
expectedInput[i] = std::toupper(output[i]);
|
|
|
expectedInput[i] = std::toupper(output[i]);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
child.writer << output;
|
|
|
|
|
|
child.writer.flush();
|
|
|
|
|
|
|
|
|
child.childStream << output;
|
|
|
|
|
|
child.childStream.flush();
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
|
|
|
|
|
|
|
|
if (child.numBytesAvailable() != 1) {
|
|
|
if (child.numBytesAvailable() != 1) {
|
|
|
RETURN_FALSE(" numBytesAvailable() did not return expected 1");
|
|
|
RETURN_FALSE(" numBytesAvailable() did not return expected 1");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
child.reader.read(&ch, 1);
|
|
|
|
|
|
|
|
|
child.childStream.read(&ch, 1);
|
|
|
|
|
|
|
|
|
int index = 0;
|
|
|
int index = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
}
|
|
|
std::fill_n(buf, sizeof(buf), 0);
|
|
|
std::fill_n(buf, sizeof(buf), 0);
|
|
|
|
|
|
|
|
|
child.reader.read(buf, nBytesAvailable);
|
|
|
|
|
|
|
|
|
child.childStream.read(buf, nBytesAvailable);
|
|
|
|
|
|
|
|
|
if (expectedInput.substr(index, nBytesAvailable) != std::string(buf)) {
|
|
|
if (expectedInput.substr(index, nBytesAvailable) != std::string(buf)) {
|
|
|
RETURN_FALSE(" reader.read() failure");
|
|
|
RETURN_FALSE(" reader.read() failure");
|
|
|
|
|
|
|
|
|
}
|
|
|
}
|
|
|
std::fill_n(buf, sizeof(buf), 0);
|
|
|
std::fill_n(buf, sizeof(buf), 0);
|
|
|
|
|
|
|
|
|
child.reader.read(buf, nBytesAvailable);
|
|
|
|
|
|
|
|
|
child.childStream.read(buf, nBytesAvailable);
|
|
|
|
|
|
|
|
|
if (expectedInput.substr(index, nBytesAvailable) != std::string(buf)) {
|
|
|
if (expectedInput.substr(index, nBytesAvailable) != std::string(buf)) {
|
|
|
RETURN_FALSE(" reader.read() failure");
|
|
|
RETURN_FALSE(" reader.read() failure");
|
|
|
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
// Send exit message.
|
|
|
// Send exit message.
|
|
|
child.writer << 'q';
|
|
|
|
|
|
child.writer.flush();
|
|
|
|
|
|
if (!child.writer) {
|
|
|
|
|
|
|
|
|
child.childStream << 'q';
|
|
|
|
|
|
child.childStream.flush();
|
|
|
|
|
|
if (!child.childStream) {
|
|
|
RETURN_FALSE(" Failure in testNonblockingReader: writer stream is bad");
|
|
|
RETURN_FALSE(" Failure in testNonblockingReader: writer stream is bad");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|