Browse Source

Implemented tests of Child read(), write(), and writeAndShrink() with strings.


git-svn-id: https://svn.microneil.com/svn/CodeDweller-Tests/trunk@43 b3372362-9eaa-4a85-aa2b-6faa1ab7c995
master
adeniz 9 years ago
parent
commit
14b01f12aa
2 changed files with 307 additions and 12 deletions
  1. 1
    1
      TestChild/childProgram.cpp
  2. 306
    11
      TestChild/testChild.cpp

+ 1
- 1
TestChild/childProgram.cpp View File

@@ -38,7 +38,7 @@ main(int argc, char *argv[]) {
// Exit?
if ('q' == ch) {
log << ch << "\"" << std::endl;
log << (char) ch << "\"" << std::endl;
break;
}

+ 306
- 11
TestChild/testChild.cpp View File

@@ -53,6 +53,177 @@ bool result;
<< ", Fail: " << nFail \
<< ", Total: " << nTotalTests << std::endl
bool doReadWrite(size_t bufSize,
size_t nominalAboveMin_ms,
size_t delta_ms,
size_t maxChar) {
try {
std::vector<std::string> cmd;
cmd.push_back(childName);
CodeDweller::Child child(cmd,
bufSize,
nominalAboveMin_ms,
delta_ms);
// Characters for testing.
char randomLetter[] = "abcdefghijklmnop#rstuvwxyz";
// Calculate how often to output a "." to indicate progress.
int maxChunks = maxChar / bufSize;
int nChunks = 0;
int nDots = 50;
int outputEveryChunk = maxChunks / nDots / 2;
if (outputEveryChunk == 0) {
outputEveryChunk = 2;
}
// Send and receive random-sized chunks of data.
size_t nChar = 0;
while (nChar < maxChar) {
nChunks++;
if (nChunks % outputEveryChunk == 0) {
std::cout << ".";
std::cout.flush();
}
int chunkSize;
std::string sentChunk, expectedChunk;
// Get a random chunk size for sending.
chunkSize = std::rand() % (bufSize * 4);
if (chunkSize + nChar > maxChar) {
chunkSize = maxChar - nChar;
}
// Generate output to child.
sentChunk.clear();
for (size_t i = 0; i < chunkSize; i++) {
sentChunk.push_back(randomLetter[std::rand() % 26]);
}
// Generated expected input from child.
expectedChunk = sentChunk;
for (int i = 0; i < expectedChunk.size(); i++) {
expectedChunk[i] = std::toupper(expectedChunk[i]);
}
// Send the data.
while (!sentChunk.empty()) {
if (child.writeAndShrink(sentChunk) == 0) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
// Read and compare while sending data.
std::string chunkFromChild;
size_t chunkFromChildSize;
(void) child.read(chunkFromChild);
chunkFromChildSize = chunkFromChild.size();
if (!chunkFromChild.empty()) {
if (chunkFromChild == expectedChunk.substr(0, chunkFromChildSize)) {
expectedChunk.erase(0, chunkFromChildSize);
} else {
std::cout << "Expected: \""
<< expectedChunk.substr(0, chunkFromChildSize)
<< "\", received \"" << chunkFromChild << "\"."
<< std::endl;
std::cout << "Remaining chunk: \"" << expectedChunk << "\""
<< std::endl;
child.write("q");
std::this_thread::sleep_for(std::chrono::milliseconds(100));
RETURN_FALSE(" comparison failure");
}
}
}
// Read and compare after all data was sent.
while (!expectedChunk.empty()) {
std::string chunkFromChild;
size_t chunkFromChildSize;
(void) child.read(chunkFromChild);
chunkFromChildSize = chunkFromChild.size();
if (0 == chunkFromChildSize) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
} else {
if (chunkFromChild == expectedChunk.substr(0, chunkFromChildSize)) {
expectedChunk.erase(0, chunkFromChildSize);
} else {
std::cout << "Expected: \""
<< expectedChunk.substr(0, chunkFromChildSize)
<< "\", received \"" << chunkFromChild << "\"."
<< std::endl;
std::cout << "Remaining chunk: \"" << expectedChunk << "\""
<< std::endl;
child.write("q");
std::this_thread::sleep_for(std::chrono::milliseconds(100));
RETURN_FALSE(" comparison failure");
}
}
}
nChar += chunkSize;
}
// Send exit message.
if (!child.write("q")) {
RETURN_FALSE(" write() failure");
}
// Verify exit.
std::this_thread::sleep_for(std::chrono::milliseconds(100));
if (!child.isDone()) {
std::cout << " Failure in testChildNonblockingReadWrite2: "
<< "Child program did not exit." << std::endl;
return false;
}
std::string errorDescription;
if (child.errorOccurred(errorDescription)) {
std::ostringstream temp;
temp << " Failure in: testChildNonBlockingReadWrite2: "
<< errorDescription;
RETURN_FALSE(temp.str());
}
child.close();
} catch (std::exception &e) {
EXCEPTION_TERM("Non-blocking reader test");
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
// ChildStream Tests ///////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
@@ -858,8 +1029,14 @@ bool testChildClose() {
try {
CodeDweller::Child child(cmd);
if (!child.write("q")) {
RETURN_FALSE(" write() failure");
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
child.close();
} catch (std::exception &e) {
EXCEPTION_TERM("close() after child exits");
return false;
@@ -956,7 +1133,7 @@ bool testChildReadWrite() {
child.open(childName);
// Write, read, put back, and reread each character.
// Write, read test.
int nLine = 0;
for (std::string &line : expectedChildOutput) {
@@ -1017,6 +1194,7 @@ bool testChildReadWrite() {
for (int i = 0; i < nTries; i++) {
nCharRead = child.read(temp, nCharToRead);
readLine += temp;
nCharToRead -= nCharRead;
@@ -1078,6 +1256,83 @@ bool testChildReadWrite() {
}
bool testChildIsFinishedWriting() {
std::vector<std::string> cmd;
cmd.push_back(childName);
size_t bufSize = 16;
std::uint16_t
nominalAboveMin_ms = 100,
delta_ms = 0;
try {
CodeDweller::Child child(cmd,
bufSize,
nominalAboveMin_ms,
delta_ms);
if (!child.isFinishedWriting()) {
RETURN_FALSE(" isFinishedWriting() failure");
}
if (!child.write("0123456789")) {
RETURN_FALSE(" write() failure");
}
// Busy wait until the data is written.
while (!child.isFinishedWriting())
;
std::this_thread::sleep_for(std::chrono::milliseconds(50));
// Writer thread should be pausing now.
if (!child.write("0123456789")) {
RETURN_FALSE(" write() failure");
}
if (child.isFinishedWriting()) {
RETURN_FALSE(" isFinishedWriting() failure");
}
std::this_thread::sleep_for(std::chrono::milliseconds(20));
if (child.isFinishedWriting()) {
RETURN_FALSE(" isFinishedWriting() failure");
}
std::this_thread::sleep_for(std::chrono::milliseconds(80));
if (!child.isFinishedWriting()) {
RETURN_FALSE(" isFinishedWriting() failure");
}
// Send exit message.
if (!child.write("q")) {
RETURN_FALSE(" write() failure");
}
// Verify exit.
std::this_thread::sleep_for(std::chrono::milliseconds(100));
if (!child.isDone()) {
std::cout << " Failure in testIsFinishedWriting: "
<< "Child program did not exit."
<< std::endl;
return false;
}
} catch (std::exception &e) {
EXCEPTION_TERM("write()/isFinishedWriting()");
return false;
}
return true;
}
bool testChildRead() {
try {
@@ -1156,7 +1411,7 @@ bool testChildRead() {
}
bool testChildNonBlockingReadWrite() {
bool testChildNonBlockingReadWrite1() {
try {
std::vector<std::string> cmd;
@@ -1236,7 +1491,9 @@ bool testChildNonBlockingReadWrite() {
std::this_thread::sleep_for(std::chrono::milliseconds(25));
if (child.read(readBuf) != bufSize) {
size_t nRead = child.read(readBuf);
if (nRead != bufSize) {
RETURN_FALSE(" read() failure");
}
@@ -1244,6 +1501,9 @@ bool testChildNonBlockingReadWrite() {
RETURN_FALSE(" read() failure)");
}
// Wait for reader thread to fill input buffer.
std::this_thread::sleep_for(std::chrono::milliseconds(25));
if (child.read(readBuf) != expectedLeftOver) {
RETURN_FALSE(" read() failure");
}
@@ -1261,7 +1521,7 @@ bool testChildNonBlockingReadWrite() {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
if (!child.isDone()) {
std::cout << " Failure in testNonblockingReader: "
std::cout << " Failure in testChildNonblockingReadWrite1: "
<< "Child program did not exit." << std::endl;
return false;
}
@@ -1271,7 +1531,7 @@ bool testChildNonBlockingReadWrite() {
if (child.errorOccurred(errorDescription)) {
std::ostringstream temp;
temp << " Failure in: testChildNonBlockingReadWrite: "
temp << " Failure in: testChildNonBlockingReadWrite1: "
<< errorDescription;
RETURN_FALSE(temp.str());
}
@@ -1287,13 +1547,48 @@ bool testChildNonBlockingReadWrite() {
}
bool testChildNonBlockingReadWrite2() {
size_t bufSize, maxChar;
std::uint16_t
nominalAboveMin_ms = 0,
delta_ms = 0;
bufSize = 16;
maxChar = 1000 * 100;
std::cout << "\n many small buffers";
std::cout.flush();
if (!doReadWrite(bufSize, nominalAboveMin_ms, delta_ms, maxChar)) {
RETURN_FALSE(" read()/write() failure");
}
bufSize = 128 * 1024;
maxChar = 1000 * 10;
std::cout << "\n one big buffer";
std::cout.flush();
if (!doReadWrite(bufSize, nominalAboveMin_ms, delta_ms, maxChar)) {
RETURN_FALSE(" read()/write() failure");
}
bufSize = 128 * 1024;
maxChar = 1000 * 1000 * 10;
std::cout << "\n many big buffers";
std::cout.flush();
if (!doReadWrite(bufSize, nominalAboveMin_ms, delta_ms, maxChar)) {
RETURN_FALSE(" read()/write() failure");
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
// End of tests ////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
int main()
{
#if 0
std::cout << "\nCodeDweller::ChildStream unit tests\n" << std::endl;
RUN_TEST(testChildStreamIsDone);
@@ -1307,17 +1602,17 @@ int main()
std::cout << "\nCodeDweller::Child unit tests\n" << std::endl;
RUN_TEST(testChildIsDone);
//RUN_TEST(testChildIsDone);
RUN_TEST(testChildIsRunning);
RUN_TEST(testChildResult);
RUN_TEST(testChildClose);
RUN_TEST(testChildOpen);
#endif
RUN_TEST(testChildIsFinishedWriting);
RUN_TEST(testChildRead);
#if 1
RUN_TEST(testChildReadWrite);
RUN_TEST(testChildNonBlockingReadWrite);
#endif
RUN_TEST(testChildNonBlockingReadWrite1);
RUN_TEST(testChildNonBlockingReadWrite2);
SUMMARY;
return 0;

Loading…
Cancel
Save