| 
				
			 | 
			
			 | 
			@@ -1589,7 +1589,6 @@ bool testChildNonBlockingReadWrite2() { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			}
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			bool testChildVectorReadWrite() {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  try {
 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			 | 
			@@ -1746,6 +1745,174 @@ bool testChildVectorReadWrite() { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			}
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			bool testChildReadDelimited() {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  try {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    std::vector<std::string> cmd;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    cmd.push_back(childName);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    size_t bufSize = 16;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    std::uint16_t
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      nominalAboveMin_ms = 15,
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      delta_ms = 0;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    CodeDweller::Child child(cmd,
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                             bufSize,
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                             nominalAboveMin_ms,
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                             delta_ms);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Check delimiter at beginning of buffer.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    std::vector<char> childInput = {'a', 'b', 'c', 'd', 'e'};
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (!child.write(childInput)) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      RETURN_FALSE("  write() failure");
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    std::this_thread::sleep_for(std::chrono::milliseconds(50));
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Check
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    std::vector<char> readVec;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (!child.readDelimited(readVec, "AB")) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      RETURN_FALSE("  readDelimited() failure");
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (!readVec.empty()) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      RETURN_FALSE("  readDelimited() failure");
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (child.readDelimited(readVec, "n")) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      RETURN_FALSE("  readDelimited() failure");
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (child.readDelimited(readVec, "nlelk;lqm;foim")) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      RETURN_FALSE("  readDelimited() failure");
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Empty buffer.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    std::string temp;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    (void) child.read(temp);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if ("CDE" != temp) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      RETURN_FALSE("  readDelimited() failure");
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Check delimiter at middle of buffer.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (!child.write(childInput)) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      RETURN_FALSE("  write() failure");
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    std::this_thread::sleep_for(std::chrono::milliseconds(50));
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Check
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    std::string readStr;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    std::string delim = "CD";
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (!child.readDelimited(readStr, delim)) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      RETURN_FALSE("  readDelimited() failure");
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if ("AB" != readStr) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      RETURN_FALSE("  readDelimited() failure");
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    delim = "n";
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (child.readDelimited(readStr, delim)) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      RETURN_FALSE("  readDelimited() failure");
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    delim = "fimsoim3m4";
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (child.readDelimited(readStr, delim)) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      RETURN_FALSE("  readDelimited() failure");
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    readStr = "orirw";
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    delim = "";
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (!child.readDelimited(readStr, delim)) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      RETURN_FALSE("  readDelimited() failure");
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (!readStr.empty()) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      RETURN_FALSE("  readDelimited() failure");
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Empty buffer.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    (void) child.read(temp);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if ("E" != temp) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      RETURN_FALSE("  readDelimited() failure");
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Check delimiter at end of buffer.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (!child.write(childInput)) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      RETURN_FALSE("  write() failure");
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    std::this_thread::sleep_for(std::chrono::milliseconds(50));
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Check
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    std::vector<char> delimVec = {'E'};
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (!child.readDelimited(readStr, delimVec)) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      RETURN_FALSE("  readDelimited() failure");
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if ("ABCD" != readStr) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      RETURN_FALSE("  readDelimited() failure");
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    delimVec[0] = 'n';
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (child.readDelimited(readStr, delimVec)) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      RETURN_FALSE("  readDelimited() failure");
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    delimVec.push_back('4');
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    delimVec.push_back(',');
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    delimVec.push_back('m');
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    delimVec.push_back('y');
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    delimVec.push_back('t');
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    delimVec.push_back('2');
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    delimVec.push_back('e');
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    delimVec.push_back('t');
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (child.readDelimited(readStr, delimVec)) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      RETURN_FALSE("  readDelimited() failure");
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Empty buffer.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    (void) child.read(temp);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if ("" != temp) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      RETURN_FALSE("  readDelimited() 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 testChildReadDelimited:  "
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					<< "Child program did not exit."  << std::endl;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      return false;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    std::string errorDescription;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (child.errorOccurred(errorDescription)) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      std::ostringstream temp;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      temp << "  Failure in: testChildReadDelimited:  "
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			           << errorDescription;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      RETURN_FALSE(temp.str());
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    child.close();
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  } catch (std::exception &e) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    EXCEPTION_TERM("testChildReadDelimited");
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    return false;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  return true;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			}
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			////////////////////////////////////////////////////////////////////////////////
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			// End of tests ////////////////////////////////////////////////////////////////
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			////////////////////////////////////////////////////////////////////////////////
 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			 | 
			@@ -1777,6 +1944,7 @@ int main() | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  RUN_TEST(testChildNonBlockingReadWrite1);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  RUN_TEST(testChildNonBlockingReadWrite2);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  RUN_TEST(testChildVectorReadWrite);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  RUN_TEST(testChildReadDelimited);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  SUMMARY;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 |