/***********************************************************************//** * @brief Print test suite information * * @param[in] chatter Chattiness (defaults to NORMAL). * @return String containing test suite information. ***************************************************************************/ std::string GTestSuite::print(const GChatter& chatter) const { // Initialise result string std::string result; // Continue only if chatter is not silent if (chatter != SILENT) { // Append header result.append("=== GTestSuite ==="); // Append information result.append("\n"+gammalib::parformat("Name")+m_name); result.append("\n"+gammalib::parformat("Number of functions")); result.append(gammalib::str(m_names.size())); result.append("\n"+gammalib::parformat("Number of executed tests")); result.append(gammalib::str(size())); result.append("\n"+gammalib::parformat("Number of errors")); result.append(gammalib::str(errors())); result.append("\n"+gammalib::parformat("Number of failures")); result.append(gammalib::str(failures())); } // endif: chatter was not silent // Return result return result; }
/***********************************************************************//** * @brief Print test suites information * * @param[in] chatter Chattiness (defaults to NORMAL). * @return String containing test suites information. ***************************************************************************/ std::string GTestSuites::print(const GChatter& chatter) const { // Initialise result string std::string result; // Continue only if chatter is not silent if (chatter != SILENT) { // Append header result.append("=== GTestSuites ==="); // Append information result.append("\n"+gammalib::parformat("Name")+m_name); result.append("\n"+gammalib::parformat("Number of test suites")); result.append(gammalib::str(size())); result.append("\n"+gammalib::parformat("Number of tests")); result.append(gammalib::str(tests())); result.append("\n"+gammalib::parformat("Number of errors")); result.append(gammalib::str(errors())); result.append("\n"+gammalib::parformat("Number of failures")); result.append(gammalib::str(failures())); // Append test suites for (int i = 0; i < size(); ++i) { result.append("\n"); result.append((*this)[i]->print(chatter)); } } // endif: chatter was not silent // Return result return result; }
void TextTestResult::printFailures(std::ostream& stream) { if (testFailures() != 0) { stream << "\n"; if (testFailures() == 1) stream << "There was " << testFailures() << " failure: " << std::endl; else stream << "There were " << testFailures() << " failures: " << std::endl; int i = 1; for (std::vector<TestFailure*>::iterator it = failures().begin(); it != failures().end(); ++it) { TestFailure* failure = *it; CppUnitException* e = failure->thrownException(); stream << std::setw(2) << i << ": " << failure->failedTest()->toString() << "\n" << " \"" << (e ? e->what() : "") << "\"\n" << " in \"" << (e ? e->fileName() : std::string()) << "\", line "; if (e == 0) { stream << "0"; } else { stream << e->lineNumber(); if (e->data2LineNumber() != CppUnitException::CPPUNIT_UNKNOWNLINENUMBER) { stream << " data lines " << e->data1LineNumber() << ", " << e->data2LineNumber(); } else if (e->data1LineNumber() != CppUnitException::CPPUNIT_UNKNOWNLINENUMBER) { stream << " data line " << e->data1LineNumber(); } } stream << "\n"; i++; } } }
void TextTestResult::printFailures (std::ostream &stream) { if ( testFailures () != 0 ) { if (testFailures () == 1) { stream << "There was " << testFailures () << " failure: " << std::endl; } else { stream << "There were " << testFailures () << " failures: " << std::endl; } printCauses(stream, failures()); } }
bool file_exists(const std::string &filename) { int readok = access(filename.c_str(), R_OK); if (readok == 0) { return true; } else { if (errno == ENOENT) { // File does not exist return false; } else { // It exists, but we can't access it failures("Error accessing file %s", filename.c_str()); } } failure("Unreachable"); }
/***********************************************************************//** * @brief Print test suites information ***************************************************************************/ std::string GTestSuites::print(void) const { // Initialise result string std::string result; // Append header result.append("=== GTestSuites ==="); result.append("\n"+parformat("Name")+m_name); result.append("\n"+parformat("Number of test suites")+str(size())); result.append("\n"+parformat("Number of tests")+str(tests())); result.append("\n"+parformat("Number of errors")+str(errors())); result.append("\n"+parformat("Number of failures")+str(failures())); // Append test suites for (int i = 0; i < size(); ++i) { result.append("\n"); result.append((*this)[i].print()); } // Return result return result; }
void TestLocalSocket::runTest(uchar dataAmnt, uchar pkgAmnt, uchar fdAmnt) { quint64 sendCount = 0; quint64 sendCountPackage = 0; quint64 sendCountData = 0; quint64 sendCountFD = 0; quint64 sendBytes = 0; // Runtime for peer in seconds int runTime = 15; // In seconds QElapsedTimer time; // Log timer QElapsedTimer logTimer; const int logInterval = 200; // In msec logTimer.start(); printf("\tRunning %d seconds\n", runTime); time.start(); while(m_localSocket && time.elapsed() < runTime * 1000) { QVERIFY2(m_localSocket->isOpen(), qPrintable(QStringLiteral("LocalSocket not open! (" + m_localSocket->errorString() + ")"))); QChar command; uchar action; QFile * file = 0; QString filename; Variant data(randomData(&action, dataAmnt, pkgAmnt, fdAmnt, &file)); // data can be invalid if we only test file descriptors as they have an limit if(dataAmnt == 0 && pkgAmnt == 0 && !data.isValid()) break; // randomData returned invalid data -> Error already printed QVERIFY(data.isValid()); // Handle filename if(file != 0) { filename = QFileInfo(*file).absoluteFilePath(); m_openFiles[filename] = file; } // if(!m_peer->m_socket->isOpen() && !m_peer->m_socket->bytesAvailable()) // { // returnLock.lockForWrite(); // failureReason = "Socket closed"; // failureReceived = true; // returnLock.unlock(); // } // qDebug("Open: %s", m_peer->m_socket->isOpen() ? "true" : "false"); switch(action) { // Send data case 0: { QByteArray dataAr(data.toByteArray()); QByteArray hash(QCryptographicHash::hash(dataAr, QCryptographicHash::Md5)); command = 'd'; // qDebug("Sending data with size %d", dataAr.size()); QVERIFY2(m_peer->writeControlData(QString(command).toLatin1() + hash.toHex() + "\n"), "Could not write data to peer!"); // size quint32 size = qToBigEndian<quint32>(dataAr.size()); // qDebug("Size written: %d", data.size()); dataAr.prepend((const char*)&size, sizeof(size)); // static quint64 totalWrittenTest = 0; // totalWrittenTest += data.size(); // qDebug("total-written (test): %llu", totalWrittenTest); qint64 written = 0; QElapsedTimer timer; timer.start(); while(m_localSocket && m_localSocket->isOpen() && written < dataAr.size() && timer.elapsed() < 30000) { qint64 tmp = m_localSocket->write(dataAr.constData() + written, dataAr.size() - written); // if(tmp < 0) // qDebug("tmp < 0! open: %s", m_localSocket->isOpen() ? "true" : "false"); QVERIFY2(tmp >= 0, qPrintable(QStringLiteral("Could not write all data to peer! (" + m_localSocket->errorString() + ")"))); written += tmp; // QCoreApplication::processEvents(); m_localSocket->waitForBytesWritten(3000); } // For debugging // printf("\t=== Data written ===\n"); // for(int i = 0; i < data.size(); i++) // printf("\t%02X", data.constData()[i]); // printf("\t\n====================\n"); QVERIFY2(written == dataAr.size(), "Could not write all data to peer!"); sendCountData++; sendBytes += dataAr.size() - sizeof(size); dataAr.clear(); // qDebug("Sent data!"); }break; // Send package case 1: { QByteArray dataAr(data.toByteArray()); QByteArray hash(QCryptographicHash::hash(dataAr, QCryptographicHash::Md5)); command = 'p'; QVERIFY2(m_peer->writeControlData(QString(command).toLatin1() + hash.toHex() + "\n"), "Could not write data to peer!"); bool result = m_localSocket->writePackage(dataAr); while(!result && m_localSocket->isOpen()) { m_localSocket->waitForPackageWritten(30000); result = m_localSocket->writePackage(dataAr); } QVERIFY2(result, "Could not write package!"); sendCountPackage++; sendBytes += dataAr.size(); dataAr.clear(); // qDebug("Sent package!"); }break; // Send file descriptor case 2: { QByteArray dataAr(filename.toLatin1()); command = 's'; QVERIFY2(m_peer->writeControlData(QString(command).toLatin1() + dataAr.toHex() + "\n"), "Could not write data to peer!"); QVERIFY2(m_localSocket->writeSocketDescriptor(data.toSocketDescriptor()), "Could not write socket descriptor!"); sendCountFD++; // qDebug("Sent socket descriptor!"); }break; } QCoreApplication::processEvents(); // qDebug("Sent data!"); sendCount++; if(logTimer.elapsed() >= logInterval) { Logger::log("Written commands (TestLocalSocket)", sendCount); logTimer.restart(); } QStringList failures(m_peer->failureMessages()); QVERIFY2(failures.isEmpty(), qPrintable(QStringLiteral("Received failures:\n\t- %1").arg(failures.join("\n\t- ")))); } Logger::log("Written commands (TestLocalSocket)", sendCount, "wB", "Waiting for bytes to be written"); printf("\tSent %llu actions (%llu data portions, %llu packages, %llu file descriptors)\n", sendCount, sendCountData, sendCountPackage, sendCountFD); quint64 sendBytesFormatted = sendBytes; QStringList formatter; formatter << "b" << "KB" << "MB" << "GB" << "TB" << "PB"; int idx = 0; while(sendBytesFormatted > 1024*10) { sendBytesFormatted /= 1024; idx++; } printf("\tSent %llu bytes (%llu %s)\n", sendBytes, sendBytesFormatted, qPrintable(formatter[idx])); printf("\tWaiting for results (This could take a while)\n"); while(m_localSocket && m_localSocket->isOpen() && m_localSocket->bytesToWrite()) { QCoreApplication::processEvents(); m_localSocket->waitForBytesWritten(10000); } // Send close command // qDebug("Sending close command!"); Logger::log("Written commands (TestLocalSocket)", sendCount, "sC", "Sent close command"); QVERIFY2(m_peer->writeControlData(QStringLiteral("c\n").toLatin1()), "Could not write data to peer!"); QCoreApplication::processEvents(); if(!m_peer->waitForTotalSuccessCount(sendCount, 20000)) { QStringList failures(m_peer->failureMessages()); QVERIFY2(failures.isEmpty(), qPrintable(QStringLiteral("Received failures:\n\t- %1").arg(failures.join("\n\t- ")))); if(m_peer->totalSuccessCount() != sendCount) Logger::log("Written commands (TestLocalSocket)", sendCount, "f", "Failed to wait for all return commands"); QVERIFY2(m_peer->totalSuccessCount() == sendCount, qPrintable(QStringLiteral("Invalid return count. Expected: %1; Got: %2").arg(sendCount).arg(m_peer->totalSuccessCount()))); } // Check signal socketDescriptorWritten() QList<quintptr> neededFdSignals; foreach(QFile * file, m_openFiles.values()) neededFdSignals.append((quintptr)file->handle()); QCoreApplication::processEvents(); QList<quintptr> emittedFdSignals(m_peer->fileDescriptorSignals()); for(int i = 0; i < emittedFdSignals.count(); i++) QVERIFY2(neededFdSignals.removeOne(emittedFdSignals[i]), qPrintable(QStringLiteral("Invalid socketDescriptorWritten() signal"))); QVERIFY2(neededFdSignals.isEmpty(), qPrintable(QStringLiteral("Missing socketDescriptorWritten() signals: %1").arg(neededFdSignals.count()))); Logger::log("Written commands (TestLocalSocket)", sendCount, "d", "Done"); }
/***********************************************************************//** * @brief Run all tests in test suite * * @return True if all tests were successful, false otherwise. * * Executes all test functions that have been appended to the test suite. * For each test function a test case is added to the test suite. ***************************************************************************/ bool GTestSuite::run(void) { // Setup the test functions. This is a pure virtual function that needs // to be implemented in the derived class. It sets the function // pointers and function names for all test functions that should be // executed. set(); // Initialise success flag bool success = true; // Loop over all functions in suite for (m_index = 0; m_index < m_functions.size(); ++m_index) { // Continue only if function is valid if (m_functions[m_index] != NULL) { // Save the number of errors and failures before test // execution. We use this after the test to see if // any failures occured. int old_errors = errors(); int old_failures = failures(); // Log the name of the test std::cout << m_names[m_index] << ": "; // Create a test of error type for function testing GTestCase* test = new GTestCase(GTestCase::ERROR_TEST, m_names[m_index]); // Add test case to test suite m_tests.push_back(test); // Set start time #ifdef _OPENMP double t_start = omp_get_wtime(); #else clock_t t_start = clock(); #endif // Execute test function try { (this->*(m_functions[m_index]))(); } catch (std::exception& e) { // Signal that test did not succeed test->has_passed(false); // Set test message to exception message test->message(e.what()); // Set type as class name test->type(typeid(e).name()); } catch (...) { // For other exceptions test->has_passed(false); test->message("Non-standard C++ exception thrown"); } // Compute elapsed time #ifdef _OPENMP double t_elapse = omp_get_wtime()-t_start; #else double t_elapse = (double)(clock() - t_start) / (double)CLOCKS_PER_SEC; #endif // Set test duration test->duration(t_elapse); // Increment number of errors if the test did not pass if (!test->has_passed()) { m_errors++; } // Log the result (".","F" or, "E") std::cout << test->print(); // Log if there are errors or failures if ((m_errors == old_errors && m_failures == old_failures)) { std::cout << " ok" << std::endl; } else { std::cout << " NOK" << std::endl; success = false; } } // endif: test case has a function pointer } // endfor: looped over tests on the stack // Reset index m_index = 0; // Return success flag return success; }